unit QImport2Wizard;

{$I VerCtrl.inc}

interface

uses
  Forms, Dialogs, QImport2XLS, QImport2ASCII, QImport2, QImport2DBF, StdCtrls,
  Grids, ComCtrls, Buttons, Controls, ExtCtrls, Classes, Db,
  Windows, fuQImport2ProgressDlg, QImport2TXTView, DBGrids, XLSFile,
  XLSMapParser, InfoPanel, QImport2XML, ToolWin, Graphics 
  {$IFDEF VCL4}, ImgList{$ENDIF};

type
  TQImport2Wizard = class(TComponent)
  private
    FAllowedImports: TAllowedImports;

    FDataSet: TDataSet;
    FDBGrid: TDBGrid;
    FListView: TListView;
    FStringGrid: TStringGrid;

    FFileName: string;
    FFormats: TQImportFormats;
    FFieldFormats: TQImportFieldFormats;
    FAbout: string;
    FVersion: string;

    FImportRecCount: integer;
    FCommitRecCount: integer;
    FCommitAfterDone: boolean;
    FErrorLog: boolean;
    FErrorLogFileName: string;
    FRewriteErrorLogFile: boolean;
    FShowErrorLog: boolean;
    FShowProgress: boolean;
    FAutoChangeExtension: boolean;
    FShowHelpButton: boolean;
    FCloseAfterImport: boolean;
    FPicture: TPicture;
    FTextViewerRows: integer;
    FCSVViewerRows: integer;
    FExcelViewerRows: integer;
    FExcelMaxColWidth: integer;

    FShowSaveLoadButtons: boolean;

    FAutoSaveTemplate: boolean;
    FAutoLoadTemplate: boolean;
    FTemplateFileName: string;
    FGoToLastPage: boolean;

    FImportDestination: TQImportDestination;
    FImportMode: TQImportMode;
    FAddType: TQImportAddType;
    FKeyColumns: TStrings;
    FGridCaptionRow: integer;
    FGridStartRow: integer;
    FConfirmOnCancel: boolean;

    FOnBeforeImport: TNotifyEvent;
    FOnAfterImport: TNotifyEvent;
    FOnImportRecord: TNotifyEvent;
    FOnImportError: TNotifyEvent;
    FOnImportErrorAdv: TNotifyEvent;
    FOnNeedCommit: TNotifyEvent;
    FOnImportCancel: TImportCancelEvent;
    FOnBeforePost: TImportBeforePostEvent;
    FOnLoadTemplate: TImportLoadTemplateEvent;
    FOnDestinationLocate: TDestinationLocateEvent;

    function IsFileName: Boolean;
    procedure SetFormats(const Value: TQImportFormats);
    procedure SetFieldFormats(const Value: TQImportFieldFormats);
    procedure SetKeyColumns(const Value: TStrings);
    procedure SetPicture(const Value: TPicture);
  protected
    procedure Notification(AComponent: TComponent;
      Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Execute;
  published
    property AllowedImports: TAllowedImports read FAllowedImports
      write FAllowedImports default [Low(TAllowedImport)..High(TAllowedImport)];

    property DataSet: TDataSet read FDataSet write FDataSet;
    property DBGrid: TDBGrid read FDBGrid write FDBGrid;
    property ListView: TListView read FListView write FListView;
    property StringGrid: TStringGrid read FStringGrid write FStringGrid;

    property FileName: string read FFileName write FFileName stored IsFileName;
    property Formats: TQImportFormats read FFormats write SetFormats;
    property FieldFormats: TQImportFieldFormats read FFieldFormats
      write SetFieldFormats;
    property About: string read FAbout write FAbout;
    property Version: string read FVersion write FVersion;

    property ImportRecCount: integer read FImportRecCount
      write FImportRecCount default 0;
    property CommitRecCount: integer read FCommitRecCount
      write FCommitRecCount default 100;
    property CommitAfterDone: boolean read FCommitAfterDone
      write FCommitAfterDone default true;
    property ErrorLog: boolean read FErrorLog write FErrorLog default false;
    property ErrorLogFileName: string read FErrorLogFileName
      write FErrorLogFileName;
    property RewriteErrorLogFile: boolean read FRewriteErrorLogFile
      write FRewriteErrorLogFile default true;
    property ShowErrorLog: boolean read FShowErrorLog
      write FShowErrorLog default false;
    property ShowProgress: boolean read FShowProgress
      write FShowProgress default true;
    property AutoChangeExtension: boolean read FAutoChangeExtension
      write FAutoChangeExtension default true;
    property ShowHelpButton: boolean read FShowHelpButton
      write FShowHelpButton default true;
    property CloseAfterImport: boolean read FCloseAfterImport
      write FCloseAfterImport default false;
    property Picture: TPicture read FPicture write SetPicture;
    property TextViewerRows: integer read FTextViewerRows
      write FTextViewerRows default 20;
    property CSVViewerRows: integer read FCSVViewerRows
      write FCSVViewerRows default 20;
    property ExcelViewerRows: integer read FExcelViewerRows
      write FExcelViewerRows default 256;
    property ExcelMaxColWidth: integer read FExcelMaxColWidth
      write FExcelMaxColWidth default 130;

    property ShowSaveLoadButtons: boolean read FShowSaveLoadButtons
      write FShowSaveLoadButtons default false;

    property TemplateFileName: string read FTemplateFileName
      write FTemplateFileName;
    property AutoLoadTemplate: boolean read FAutoLoadTemplate
      write FAutoLoadTemplate default false;
    property AutoSaveTemplate: boolean read FAutoSaveTemplate
      write FAutoSaveTemplate default false;
    property GoToLastPage: boolean read FGoToLastPage
      write FGoToLastPage default false;

    property ImportDestination: TQImportDestination read FImportDestination
      write FImportDestination default qidDataSet;
    property ImportMode: TQImportMode read FImportMode write FImportMode
      default qimInsertAll;
    property AddType: TQImportAddType read FAddType
      write FAddType default qatAppend;
    property KeyColumns: TStrings read FKeyColumns write SetKeyColumns;
    property GridCaptionRow: integer read FGridCaptionRow
      write FGridCaptionRow default -1;
    property GridStartRow: integer read FGridStartRow
      write FGridStartRow default -1;
    property ConfirmOnCancel: boolean read FConfirmOnCancel
      write FConfirmOnCancel default true;

    property OnBeforeImport: TNotifyEvent read FOnBeforeImport
      write FOnBeforeImport;
    property OnAfterImport: TNotifyEvent read FOnAfterImport
      write FOnAfterImport;
    property OnImportRecord: TNotifyEvent read FOnImportRecord
      write FOnImportRecord;
    property OnImportError: TNotifyEvent read FOnImportError
      write FOnImportError;
    property OnImportErrorAdv: TNotifyEvent read FOnImportErrorAdv
      write FOnImportErrorAdv;
    property OnNeedCommit: TNotifyEvent read FOnNeedCommit
      write FOnNeedCommit;
    property OnImportCancel: TImportCancelEvent read FOnImportCancel
      write FOnImportCancel;
    property OnBeforePost: TImportBeforePostEvent read FOnBeforePost
      write FOnBeforePost;
    property OnLoadTemplate: TImportLoadTemplateEvent read FOnLoadTemplate
      write FOnLoadTemplate;
    property OnDestinationLocate: TDestinationLocateEvent
      read FOnDestinationLocate write FOnDestinationLocate;
  end;

  TQImport2WizardF = class(TForm)
    impDBF: TQImport2DBF;
    impASCII: TQImport2ASCII;
    impXLS: TQImport2XLS;
    paButtons: TPanel;
    Bevel1: TBevel;
    bHelp: TButton;
    bBack: TButton;
    bNext: TButton;
    bCancel: TButton;
    bOk: TButton;
    pgImport: TPageControl;
    tsImportType: TTabSheet;
    tsTXTOptions: TTabSheet;
    tsDBFOptions: TTabSheet;
    tsExcelOptions: TTabSheet;
    grpImportTypes: TGroupBox;
    laComma: TLabel;
    rbtXLS: TRadioButton;
    rbtDBF: TRadioButton;
    rbtTXT: TRadioButton;
    rbtCSV: TRadioButton;
    cbComma: TComboBox;
    laSourceFileName: TLabel;
    edtFileName: TEdit;
    Bevel6: TBevel;
    opnDialog: TOpenDialog;
    spbBrowse: TSpeedButton;
    tsCommitOptions: TTabSheet;
    laTXTStep_02: TLabel;
    Bevel2: TBevel;
    laTXTSkipLines: TLabel;
    edtTXTSkipLines: TEdit;
    laStep_03: TLabel;
    Bevel3: TBevel;
    lstDBFDataSet: TListView;
    lstDBF: TListView;
    lstDBFMap: TListView;
    bDBFAdd: TSpeedButton;
    bDBFRemove: TSpeedButton;
    laStep_04: TLabel;
    Bevel4: TBevel;
    laStep_02: TLabel;
    Bevel5: TBevel;
    tsFormats: TTabSheet;
    laStep_06: TLabel;
    Bevel7: TBevel;
    pgFormats: TPageControl;
    tshBaseFormats: TTabSheet;
    grpDateTimeFormats: TGroupBox;
    laShortDateFormat: TLabel;
    laLongDateFormat: TLabel;
    laShortTimeFormat: TLabel;
    laLongTimeFormat: TLabel;
    edtShortDateFormat: TEdit;
    edtLongDateFormat: TEdit;
    edtShortTimeFormat: TEdit;
    edtLongTimeFormat: TEdit;
    tshDataFormats: TTabSheet;
    lstFormatFields: TListView;
    ilWizard: TImageList;
    odTemplate: TOpenDialog;
    btnSaveTemplate: TSpeedButton;
    sdTemplate: TSaveDialog;
    bDBFAutoFill: TSpeedButton;
    bDBFClear: TSpeedButton;
    laQuote: TLabel;
    tsCSVOptions: TTabSheet;
    laStep_07: TLabel;
    Bevel15: TBevel;
    sgrCSV: TStringGrid;
    pgFieldOptions: TPageControl;
    tsFieldTuning: TTabSheet;
    laGeneratorValue: TLabel;
    edtGeneratorValue: TEdit;
    laGeneratorStep: TLabel;
    edtGeneratorStep: TEdit;
    laConstantValue: TLabel;
    edtConstantValue: TEdit;
    laNullValue: TLabel;
    edtNullValue: TEdit;
    laDefaultValue: TLabel;
    edtDefaultValue: TEdit;
    laLeftQuote: TLabel;
    edtLeftQuote: TEdit;
    laRightQuote: TLabel;
    edtRightQuote: TEdit;
    laQuoteAction: TLabel;
    cmbQuoteAction: TComboBox;
    laCharCase: TLabel;
    cmbCharCase: TComboBox;
    laCharSet: TLabel;
    cmbCharSet: TComboBox;
    Bevel13: TBevel;
    grpSeparators: TGroupBox;
    laDecimalSeparator: TLabel;
    edtDecimalSeparator: TEdit;
    laThousandSeparator: TLabel;
    edtThousandSeparator: TEdit;
    laDateSeparator: TLabel;
    edtDateSeparator: TEdit;
    laTimeSeparator: TLabel;
    edtTimeSeparator: TEdit;
    cbQuote: TComboBox;
    pcLastStep: TPageControl;
    tshCommit: TTabSheet;
    tshAdvanced: TTabSheet;
    grpImportCount: TGroupBox;
    laImportRecCount_01: TLabel;
    laImportRecCount_02: TLabel;
    chImportAllRecords: TCheckBox;
    edtImportRecCount: TEdit;
    grpCommit: TGroupBox;
    laCommitRecCount_01: TLabel;
    laCommitRecCount_02: TLabel;
    chCommitAfterDone: TCheckBox;
    edtCommitRecCount: TEdit;
    chDBFSkipDeleted: TCheckBox;
    sdErrorLog: TSaveDialog;
    chCloseAfterImport: TCheckBox;
    pcXLSFile: TPageControl;
    paXLSFieldsAndRanges: TPanel;
    lvXLSFields: TListView;
    lvXLSRanges: TListView;
    tbXLSRanges: TToolBar;
    tbtXLSAddRange: TToolButton;
    tbtXLSEditRange: TToolButton;
    tbtXLSDelRange: TToolButton;
    tbXLSUtils: TToolBar;
    tbtXLSAutoFillCols: TToolButton;
    tbtXLSAutoFillRows: TToolButton;
    tbtXLSMoveRangeUp: TToolButton;
    tbtXLSMoveRangeDown: TToolButton;
    tbtSeparator_01: TToolButton;
    tbtXLSClearFieldRanges: TToolButton;
    grpErrorLog: TGroupBox;
    laErrorLogFileName: TLabel;
    bvErrorLogFileName: TBevel;
    bErrorLogFileName: TSpeedButton;
    chEnableErrorLog: TCheckBox;
    chShowErrorLog: TCheckBox;
    edErrorLogFileName: TEdit;
    chRewriteErrorLogFile: TCheckBox;
    rgImportMode: TRadioGroup;
    lvAvailableColumns: TListView;
    laAvailableColumns: TLabel;
    bAllToRight: TSpeedButton;
    bOneToRirght: TSpeedButton;
    bOneToLeft: TSpeedButton;
    bAllToLeft: TSpeedButton;
    lvSelectedColumns: TListView;
    laSelectedColumns: TLabel;
    rgAddType: TRadioGroup;
    laReplacements: TLabel;
    gbTemplateOptions: TGroupBox;
    btnLoadTemplate: TSpeedButton;
    chGoToLastPage: TCheckBox;
    chAutoSaveTemplate: TCheckBox;
    pbDBFAdd: TPaintBox;
    pbDBFAutoFill: TPaintBox;
    pbDBFRemove: TPaintBox;
    pbDBFClear: TPaintBox;
    lvCSVFields: TListView;
    tbCSV: TToolBar;
    tbtCSVAutoFill: TToolButton;
    tbtCSVClear: TToolButton;
    laCSVSkipLines: TLabel;
    edtCSVSkipLines: TEdit;
    cbCSVColNumber: TComboBox;
    laCSVColNumber: TLabel;
    lvTXTFields: TListView;
    tbTXT: TToolBar;
    tbtTXTClear: TToolButton;
    laXLSSkipCols: TLabel;
    edXLSSkipCols: TEdit;
    laXLSSkipRows: TLabel;
    edXLSSkipRows: TEdit;
    rbtXML: TRadioButton;
    tsXMLOptions: TTabSheet;
    laStep_05: TLabel;
    Bevel8: TBevel;
    lvXMLDataSet: TListView;
    lvXML: TListView;
    lvXMLMap: TListView;
    bXMLAdd: TSpeedButton;
    pbXMLAdd: TPaintBox;
    bXMLAutoFill: TSpeedButton;
    pbXMLAutoFill: TPaintBox;
    bXMLRemove: TSpeedButton;
    pbXMLRemove: TPaintBox;
    bXMLClear: TSpeedButton;
    pbXMLClear: TPaintBox;
    impXML: TQImport2XML;
    mmBooleanTrue: TMemo;
    laBooleanTrue: TLabel;
    mmBooleanFalse: TMemo;
    laBooleanFalse: TLabel;
    laNullValues: TLabel;
    mmNullValues: TMemo;
    Image: TImage;
    tbtXLSClearAllRanges: TToolButton;
    lvXLSSelection: TListView;
    lvReplacements: TListView;
    tbReplacements: TToolBar;
    tbtAddReplacement: TToolButton;
    tbtEditReplacement: TToolButton;
    tbtDelReplacement: TToolButton;
    chXMLWriteOnFly: TCheckBox;
    laTemplateFileName: TLabel;
    laTemplateFileNameTag: TLabel;
    procedure BeforeImport(Sender: TObject);
    procedure AfterImport(Sender: TObject);
    procedure ImportRecord(Sender: TObject);
    procedure ImportError(Sender: TObject);
    procedure ImportErrorAdv(Sender: TObject);
    procedure NeedCommit(Sender: TObject);
    procedure ImportCancel(Sender: TObject; var Continue: Boolean);
    procedure BeforePost(Sender: TObject; Row: TQImportRow;
      var Accept: Boolean);
    procedure DestinationLocate(Sender: TObject; KeyColumns: TStrings;
      Row: TQImportRow; var KeyFields: String; var KeyValues: Variant);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure spbBrowseClick(Sender: TObject);
    procedure rbtClick(Sender: TObject);
    procedure edtFileNameChange(Sender: TObject);
    procedure chGoToLastPageClick(Sender: TObject);
    procedure chAutoSaveTemplateClick(Sender: TObject);
    procedure bNextClick(Sender: TObject);
    procedure bBackClick(Sender: TObject);
    procedure bDBFAddClick(Sender: TObject);
    procedure bDBFRemoveClick(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure bOkClick(Sender: TObject);
    procedure bHelpClick(Sender: TObject);
    procedure edtGeneratorValueChange(Sender: TObject);
    procedure edtGeneratorStepChange(Sender: TObject);
    procedure edtConstantValueChange(Sender: TObject);
    procedure edtNullValueChange(Sender: TObject);
    procedure edtDefaultValueChange(Sender: TObject);
    procedure edtLeftQuoteChange(Sender: TObject);
    procedure edtRightQuoteChange(Sender: TObject);
    procedure cmbQuoteActionChange(Sender: TObject);
    procedure cmbCharCaseChange(Sender: TObject);
    procedure cmbCharSetChange(Sender: TObject);
    procedure lstFormatFieldsChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure pgFormatsChange(Sender: TObject);
    procedure btnLoadTemplateClick(Sender: TObject);
    procedure edtShortDateFormatChange(Sender: TObject);
    procedure edtLongDateFormatChange(Sender: TObject);
    procedure edtShortTimeFormatChange(Sender: TObject);
    procedure edtLongTimeFormatChange(Sender: TObject);
    procedure chCommitAfterDoneClick(Sender: TObject);
    procedure edtCommitRecCountChange(Sender: TObject);
    procedure chImportAllRecordsClick(Sender: TObject);
    procedure edtImportRecCountChange(Sender: TObject);
    procedure chEnableErrorLogClick(Sender: TObject);
    procedure edErrorLogFileNameChange(Sender: TObject);
    procedure bErrorLogFileNameClick(Sender: TObject);
    procedure chRewriteErrorLogFileClick(Sender: TObject);
    procedure chShowErrorLogClick(Sender: TObject);
    procedure edtTXTSkipLinesChange(Sender: TObject);
    procedure btnSaveTemplateClick(Sender: TObject);
    procedure bDBFAutoFillClick(Sender: TObject);
    procedure bDBFClearClick(Sender: TObject);
    procedure btnXLSAutoFillColsClick(Sender: TObject);
    procedure btnXLSAutoFillRowsClick(Sender: TObject);
    procedure btnCSVAutoFillClick(Sender: TObject);
    procedure bCancelClick(Sender: TObject);
    procedure lstDBFDataSetChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure lstDBFChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure lstDBFMapChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure sgrCSVDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure edtCSVSkipLinesChange(Sender: TObject);
    procedure btnCSVClearClick(Sender: TObject);
    procedure sgrCSVMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure rgImportModeClick(Sender: TObject);
    procedure rgAddTypeClick(Sender: TObject);
    procedure edtDecimalSeparatorExit(Sender: TObject);
    procedure edtThousandSeparatorExit(Sender: TObject);
    procedure edtDateSeparatorExit(Sender: TObject);
    procedure edtTimeSeparatorExit(Sender: TObject);
    procedure cbQuoteExit(Sender: TObject);
    procedure cbCommaExit(Sender: TObject);
    procedure bAllToRightClick(Sender: TObject);
    procedure bOneToRirghtClick(Sender: TObject);
    procedure bOneToLeftClick(Sender: TObject);
    procedure bAllToLeftClick(Sender: TObject);
    procedure lvAvailableColumnsDblClick(Sender: TObject);
    procedure lvSelectedColumnsDblClick(Sender: TObject);
    procedure KeyColumnsDragOver(Sender, Source: TObject; X,
      Y: Integer; State: TDragState; var Accept: Boolean);
    procedure KeyColumnsDragDrop(Sender, Source: TObject; X,
      Y: Integer);
    procedure chDBFSkipDeletedClick(Sender: TObject);
    procedure chCloseAfterImportClick(Sender: TObject);
{    procedure lvXLSFieldsSelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);}
    procedure tbtXLSAddRangeClick(Sender: TObject);
    procedure tbtXLSEditRangeClick(Sender: TObject);
    procedure tbtXLSMoveRangeUpClick(Sender: TObject);
    procedure tbtXLSMoveRangeDownClick(Sender: TObject);
    procedure tbtXLSDelRangeClick(Sender: TObject);
    procedure tbtXLSClearFieldRangesClick(Sender: TObject);
    procedure pbDBFAddPaint(Sender: TObject);
    procedure bDBFAddMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bDBFAddMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbDBFAutoFillPaint(Sender: TObject);
    procedure bDBFAutoFillMouseDown(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure bDBFAutoFillMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbDBFRemovePaint(Sender: TObject);
    procedure bDBFRemoveMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bDBFRemoveMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbDBFClearPaint(Sender: TObject);
    procedure bDBFClearMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bDBFClearMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure lvCSVFieldsChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure cbCSVColNumberChange(Sender: TObject);
    procedure lvTXTFieldsChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure edXLSSkipColsChange(Sender: TObject);
    procedure edXLSSkipRowsChange(Sender: TObject);
    procedure lvXLSRangesDblClick(Sender: TObject);
    procedure bXMLAddClick(Sender: TObject);
    procedure bXMLAutoFillClick(Sender: TObject);
    procedure bXMLRemoveClick(Sender: TObject);
    procedure bXMLClearClick(Sender: TObject);
    procedure bXMLAddMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bXMLAddMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbXMLAddPaint(Sender: TObject);
    procedure bXMLAutoFillMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bXMLAutoFillMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbXMLAutoFillPaint(Sender: TObject);
    procedure bXMLRemoveMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bXMLRemoveMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbXMLRemovePaint(Sender: TObject);
    procedure bXMLClearMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure bXMLClearMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pbXMLClearPaint(Sender: TObject);
    procedure tbtTXTClearClick(Sender: TObject);
    procedure tbtXLSClearAllRangesClick(Sender: TObject);
    procedure lvXLSRangesChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure tbtAddReplacementClick(Sender: TObject);
    procedure lvReplacementsChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure tbtEditReplacementClick(Sender: TObject);
    procedure tbtDelReplacementClick(Sender: TObject);
    procedure lvReplacementsDblClick(Sender: TObject);
    procedure lvXLSFieldsChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure chXMLWriteOnFlyClick(Sender: TObject);
    procedure lvXLSFieldsEnter(Sender: TObject);
    procedure lvXLSFieldsExit(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    FImportType: TAllowedImport;
    FComma: char;
    FQuote: char;
    FFileName: string;
    FGoToLastPage: boolean;
    FAutoSaveTemplate: boolean;
    FImport: TQImport2;

    FStep: integer;

    FDataSet: TDataSet;
    FDBGrid: TDBGrid;
    FListView: TListView;
    FStringGrid: TStringGrid;

    FImportMode: TQImportMode;
    FAddType: TQImportAddType;

    FShift: TShiftState;
    FProgress: TfmQImport2ProgressDlg;
    FTotalRecCount: integer;
    FDataFormats: TQImportFieldFormats;
    FNeedLoadFile: boolean;

    FDBFSkipDeleted: boolean;

    FTXTItemIndex: integer;
    FTXTSkipLines: integer;
    FTXTClearing: boolean;

    FCSVItemIndex: integer;
    FCSVSkipLines: integer;

    FXLSFile: TXLSFile;
    FXLSSkipRows: integer;
    FXLSSkipCols: integer;
    FXLSIsEditingGrid: boolean;
    FXLSGridSelection: TMapRow;
    FXLSDefinedRanges: TMapRow; 

    FXMLWriteOnFly: boolean; 

    FDecimalSeparator: char;
    FThousandSeparator: char;
    FShortDateFormat: string;
    FLongDateFormat: string;
    FDateSeparator: char;
    FShortTimeFormat: string;
    FLongTimeFormat: string;
    FTimeSeparator: char;

    FCommitAfterDone: boolean;
    FCommitRecCount: integer;
    FImportRecCount: integer;
    FCloseAfterImport: boolean;
    FEnableErrorLog: boolean;
    FErrorLogFileName: string;
    FRewriteErrorLogFile: boolean;
    FShowErrorLog: boolean;

    FLoadingFormatItem: boolean;
    FFormatItem: TListItem;

    FTmpFileName: string;

    procedure SetImportType(const Value: TAllowedImport);

    procedure SetCaptions;

    procedure TuneOpenDialog;
    procedure ChangeExtension;
    procedure TuneCSVControls;

    procedure SetFileName(const Value: string);
    procedure SetGoToLastPage(Value: boolean);
    procedure SetAutoSaveTemplate(Value: boolean);

    procedure FillCombosAndLists;
    procedure FillKeyColumns(Strings: TStrings);
    procedure MoveToSelected(Source, Destination: TListView;
      All: boolean; Index: integer);

    function GetWizard: TQImport2Wizard;
    function GetTemplateFileName: string;
    function GetAutoLoadTemplate: boolean;
    function GetImportDestination: TQImportDestination;
    function GetGridCaptionRow: integer;
    function GetGridStartRow: integer;
    function GetKeyColumns: TStrings;

    procedure SetComma(const Value: char);
    procedure SetQuote(const Value: char);
    procedure SetStep(const Value: integer);
    procedure ShowTip(Parent: TWinControl; Left, Top, Height, Width: integer;
      const Tip: string);

    function AllowedImportFileType(const AFileName: string): Boolean;
    function ImportTypeEquivFileType(const AFileName: string): Boolean;
    function ImportTypeStr(AImportType: TAllowedImport): string;

    //---- DBF page's methods
    procedure DBFFillList;
    procedure DBFClearList;
    procedure DBFFillTableList;
    procedure DBFClearTableList;
    procedure DBFTune;
    function DBFReady: boolean;

    //---- XML page's methods
    procedure XMLFillList;
    procedure XMLClearList;
    procedure XMLFillTableList;
    procedure XMLClearTableList;
    procedure XMLTune;
    function XMLReady: boolean;

    //---- TXT page's methods
    procedure TXTFillCombo;
    procedure TXTClearCombo;
    procedure TXTTune;
    function TXTReady: boolean;
    procedure TXTExtractPosSize(const S: string; var Position, Size: integer);
    procedure TXTViewerChangeSelection(Sender: TObject);
    procedure TXTViewerDeleteArrow(Sender: TObject; Position: integer);
    procedure TXTViewerMoveArrow(Sender: TObject; OldPos, NewPos: integer);
    procedure TXTViewerIntersectArrows(Sender: TObject; Position: integer);

    //---- CSV page's methods
    procedure CSVFillCombo;
    procedure CSVClearCombo;
    procedure CSVTune;
    function CSVReady: boolean;
    function CSVCol: integer;
    procedure CSVFillGrid;

    //---- XLS page's methods
    procedure XLSFillFieldList;
    procedure XLSClearFieldList;
    procedure XLSClearDataSheets;
    procedure XLSFillGrid;
    procedure XLSDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
      State: TGridDrawState);
    procedure XLSMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure XLSSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure XLSGridExit(Sender: TObject);
    procedure XLSGridKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure XLSGridClick(Sender: TObject);

    procedure XLSStartEditing;
    procedure XLSFinishEditing;
    procedure XLSApplyEditing;
    procedure XLSDeleteSelectedRanges;

    function XLSGetCurrentGrid: TStringGrid;
    procedure XLSRepaintCurrentGrid;
    procedure XLSFillSelection;

    procedure XLSTune;
    function  XLSReady: boolean;

    //---- Formats
    procedure FormatsFillList;
    procedure FormatsClearList;
    procedure TuneFormats;
    procedure SetEnabledDataFormatControls;
    procedure ShowFormatItem(Item: TListItem);

    //---- Utilities
    procedure LoadTemplateFromFile(const AFileName: string);
    procedure SaveTemplateToFile(const AFileName: string);
    procedure SetTitle;

    procedure TuneStart;
    procedure TuneFinish;
    procedure TuneMap;
    procedure TuneButtons;
    function StartReady: boolean;

    //---- Property's methods
    procedure SetXLSSkipCols(const Value: integer);
    procedure SetXLSSkipRows(const Value: integer);
    procedure SetDBFSkipDeleted(const Value: boolean);
    procedure SetTXTSkipLines(const Value: integer);
    procedure SetCSVSkipLines(const Value: integer);
    procedure SetXMLWriteOnFly(const Value: boolean); 

    procedure SetDecimalSeparator(const Value: char);
    procedure SetThousandSeparator(const Value: char);
    procedure SetShortDateFormat(const Value: string);
    procedure SetLongDateFormat(const Value: string);
    procedure SetDateSeparator(const Value: char);
    procedure SetShortTimeFormat(const Value: string);
    procedure SetLongTimeFormat(const Value: string);
    procedure SetTimeSeparator(const Value: char);

    procedure SetCommitAfterDone(const Value: boolean);
    procedure SetCommitRecCount(const Value: integer);
    procedure SetImportRecCount(const Value: integer);
    procedure SetCloseAfterImport(const Value: boolean);
    procedure SetEnableErrorLog(const Value: boolean);
    procedure SetErrorLogFileName(const Value: string);
    procedure SetRewriteErrorLogFile(const Value: boolean);
    procedure SetShowErrorLog(const Value: boolean);

    procedure SetImportMode(const Value: TQImportMode);
    procedure SetAddType(const Value: TQImportAddType);

    procedure ApplyDataFormats(AImport: TQImport2);
  protected
    vwTXT: TQImport2TXTViewer;
    paTip: TInfoPanel;
    property Wizard: TQImport2Wizard read GetWizard;
    property TemplateFileName: string read GetTemplateFileName;
    property AutoLoadTemplate: boolean read GetAutoLoadTemplate;
    property ImportDestination: TQImportDestination read GetImportDestination;
    property GridCaptionRow: integer read GetGridCaptionRow;
    property GridStartRow: integer read GetGridStartRow;
    property KeyColumns: TStrings read GetKeyColumns;

    property ImportType: TAllowedImport read FImportType write SetImportType;
    property FileName: string read FFileName write SetFileName;
    property GoToLastPage: boolean read FGoToLastPage write SetGoToLastPage;
    property AutoSaveTemplate: boolean read FAutoSaveTemplate
      write SetAutoSaveTemplate;

    property DataSet: TDataSet read FDataSet write FDataSet;
    property DBGrid: TDBGrid read FDBGrid write FDBGrid;
    property ListView: TListView read FListView write FListView;
    property StringGrid: TStringGrid read FStringGrid write FStringGrid;

    property Comma: char read FComma write SetComma;
    property Quote: char read FQuote write SetQuote;
    property Step: integer read FStep write SetStep;

    property FieldFormats: TQImportFieldFormats read FDataFormats
      write FDataFormats;

    // XLS
    property XLSSkipCols: integer read FXLSSkipCols write SetXLSSkipCols;
    property XLSSkipRows: integer read FXLSSkipRows write SetXLSSkipRows;

    // DBF
    property DBFSkipDeleted: boolean read FDBFSkipDeleted
      write SetDBFSkipDeleted;

    // TXT
    property TXTSkipLines: integer read FTXTSkipLines write SetTXTSkipLines;

    // CSV
    property CSVSkipLines: integer read FCSVSkipLines write SetCSVSkipLines;

    // XML
    property XMLWriteOnFly: boolean read FXMLWriteOnFly write SetXMLWriteOnFly; 

    // Base format
    property DecimalSeparator: char read FDecimalSeparator
      write SetDecimalSeparator;
    property ThousandSeparator: char read FThousandSeparator
      write SetThousandSeparator;
    property ShortDateFormat: string read FShortDateFormat
      write SetShortDateFormat;
    property LongDateFormat: string read FLongDateFormat
      write SetLongDateFormat;
    property DateSeparator: char read FDateSeparator write SetDateSeparator;
    property ShortTimeFormat: string read FShortTimeFormat
      write SetShortTimeFormat;
    property LongTimeFormat: string read FLongTimeFormat
      write SetLongTimeFormat;
    property TimeSeparator: char read FTimeSeparator write SetTimeSeparator;

    //---- Last Step
    property CommitAfterDone: boolean read FCommitAfterDone
      write SetCommitAfterDone;
    property CommitRecCount: integer read FCommitRecCount
      write SetCommitRecCount;
    property ImportRecCount: integer read FImportRecCount
      write SetImportRecCount;
    property CloseAfterImport: boolean read FCloseAfterImport
      write SetCloseAfterImport;
    property EnableErrorLog: boolean read FEnableErrorLog
      write SetEnableErrorLog;
    property ErrorLogFileName: string read FErrorLogFileName
      write SetErrorLogFileName;
    property RewriteErrorLogFile: boolean read FRewriteErrorLogFile
      write SetRewriteErrorLogFile;
    property ShowErrorLog: boolean read FShowErrorLog
      write SetShowErrorLog;

    property ImportMode: TQImportMode read FImportMode
      write SetImportMode;
    property AddType: TQImportAddType read FAddType
      write SetAddType;
  public
    property Import: TQImport2 read FImport write FImport;
  end;

implementation

uses {$IFDEF WIN32}QImport2StrIDs{$ENDIF}
     {$IFDEF LINUX}QImport2Consts, QImport2Common, QImport2Common, SysUtils, SysUtils, SysUtils, SysUtils, SysUtils, SysUtils, SysUtils{$ENDIF}, DBFFile, fuQImport2Loading, Math,
     QImport2Common {$IFDEF VCL6}, Variants{$ENDIF}, SysUtils, Messages,
     IniFiles, XLSUtily, XLSCalculate, fuQImport2XLSRangeEdit,
     fuQImport2ReplacementEdit;

{$R *.DFM}

{ TQImport2Wizard }

constructor TQImport2Wizard.Create(AOwner: TComponent);
begin
  inherited;
  FAllowedImports := [Low(TAllowedImport)..High(TAllowedImport)];
  FImportRecCount := 0;
  FCommitRecCount := 100;
  FCommitAfterDone := true;
  FErrorLog := false;
  FErrorLogFileName := 'error.log';
  FRewriteErrorLogFile := true;
  FShowErrorLog := false;
  FShowProgress := true;
  FAutoChangeExtension := true;
  FShowHelpButton := true;
  FCloseAfterImport := false;
  FFormats := TQImportFormats.Create;
  FFieldFormats := TQImportFieldFormats.Create(Self);

  FShowSaveLoadButtons := false;
  FAutoLoadTemplate := false;
  FAutoSaveTemplate := false;
  FGoToLastPage := false;

  FImportDestination := qidDataSet;
  FImportMode := qimInsertAll;
  FAddType := qatInsert;
  FKeyColumns := TStringList.Create;
  FGridCaptionRow := -1;
  FGridStartRow := -1;
  FConfirmOnCancel := true;

  FPicture := TPicture.Create;

  FTextViewerRows := 20;
  FCSVViewerRows := 20;
  FExcelViewerRows := 256;
  FExcelMaxColWidth := 130;
end;

destructor TQImport2Wizard.Destroy;
begin
  FPicture.Free;
  FFieldFormats.Free;
  FFormats.Free;
  FKeyColumns.Free;
  inherited;
end;

procedure TQImport2Wizard.Execute;
begin
  if AllowedImports = [] then raise EQImportError.Create({$IFDEF WIN32}QImportLoadStr(QIE_AllowedImportsEmpty){$ENDIF}
                                                         {$IFDEF LINUX}QIE_AllowedImportsEmpty{$ENDIF});
  QImportCheckDestination(false, ImportDestination, DataSet, DBGrid, ListView,
    StringGrid);
  with TQImport2WizardF.Create(Self) do
    try
      ShowModal;
    finally
      Free;
    end;
end;

procedure TQImport2Wizard.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and (AComponent = FDataSet)
    then FDataSet := nil;
  if (Operation = opRemove) and (AComponent = FDBGrid)
    then FDBGrid := nil;
  if (Operation = opRemove) and (AComponent = FListView)
    then FListView := nil;
  if (Operation = opRemove) and (AComponent = FStringGrid)
    then FStringGrid := nil;
end;

function TQImport2Wizard.IsFileName: Boolean;
begin
  Result := FFileName <> EmptyStr;
end;

procedure TQImport2Wizard.SetFormats(const Value: TQImportFormats);
begin
  FFormats.Assign(Value);
end;

procedure TQImport2Wizard.SetFieldFormats(const Value: TQImportFieldFormats);
begin
  FFieldFormats.Assign(Value);
end;

procedure TQImport2Wizard.SetKeyColumns(const Value: TStrings);
begin
  FKeyColumns.Assign(Value);
end;

procedure TQImport2Wizard.SetPicture(const Value: TPicture);
begin
  FPicture.Assign(Value);
end;

{ TQImportWizardF }

const
  FileExts: array[0..4] of string[4] = ('.xls', '.dbf', '.xml', '.txt', '.csv');

procedure TQImport2WizardF.BeforeImport(Sender: TObject);
begin
  FTotalRecCount := (Sender as TQImport2).TotalRecCount;
  if Assigned(FProgress) then begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_STATE, 1);
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_ROWCOUNT, FTotalRecCount);
    Application.ProcessMessages;
  end;
  if Assigned(Wizard.OnBeforeImport) then Wizard.OnBeforeImport(Wizard);
end;

procedure TQImport2WizardF.AfterImport(Sender: TObject);
begin
  if Assigned(FProgress) then begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_FINISH, Integer(ShowErrorLog));
    if not Import.Canceled then
      PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_STATE, 3);
    Application.ProcessMessages;
  end;
  if Assigned(Wizard.OnAfterImport) then Wizard.OnAfterImport(Wizard);
end;

procedure TQImport2WizardF.ImportRecord(Sender: TObject);
begin
  if Assigned(FProgress) then begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_IMPORT,
      Integer(Import.LastAction));
    Application.ProcessMessages;
  end;
  if Assigned(Wizard.OnImportRecord) then
    Wizard.OnImportRecord(Wizard);
end;

procedure TQImport2WizardF.ImportError(Sender: TObject);
begin
  if Assigned(FProgress) then
  begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_ERROR, 1);
    Application.ProcessMessages;
  end;
  if Assigned(Wizard.OnImportRecord) then
    Wizard.OnImportRecord(Wizard);
  if Assigned(Wizard.OnImportError) then
    Wizard.OnImportError(Wizard);
end;

procedure TQImport2WizardF.ImportErrorAdv(Sender: TObject);
begin
  if Assigned(FProgress) then
  begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_ERROR_ADV, 1);
    Application.ProcessMessages;
  end;
  if Assigned(Wizard.OnImportErrorAdv) then
    Wizard.OnImportErrorAdv(Wizard);
end;

procedure TQImport2WizardF.NeedCommit(Sender: TObject);
begin
  if Assigned(FProgress) then begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_COMMIT, 0);
    Application.ProcessMessages;
  end;
  if Assigned(Wizard.OnNeedCommit) then Wizard.OnNeedCommit(Self);
end;

procedure TQImport2WizardF.ImportCancel(Sender: TObject; var Continue: Boolean);
begin
  if Assigned(FProgress) then begin
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_STATE, 4);
    Application.ProcessMessages;
  end;
  Continue := Application.MessageBox(PChar({$IFDEF WIN32}QImportLoadStr(QIW_NeedCancel){$ENDIF}
                                           {$IFDEF LINUX}QIW_NeedCancel{$ENDIF}),
                            PChar({$IFDEF WIN32}QImportLoadStr(QIW_NeedCancelCaption){$ENDIF}
                                  {$IFDEF LINUX}QIW_NeedCancelCaption{$ENDIF}),
                            MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2) = ID_NO;
  if Assigned(Wizard.OnImportCancel) then Wizard.OnImportCancel(Wizard, Continue);
  if Assigned(FProgress) then begin
    if Continue then
      PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_STATE, 5)
    else PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_STATE, 2);
    Application.ProcessMessages;
  end;
end;

procedure TQImport2WizardF.BeforePost(Sender: TObject;
  Row: TQImportRow; var Accept: Boolean);
begin
  if Assigned(Wizard.OnBeforePost) then
    Wizard.OnBeforePost(Sender, Row, Accept);
end;

procedure TQImport2WizardF.DestinationLocate(Sender: TObject;
  KeyColumns: TStrings; Row: TQImportRow; var KeyFields: String;
  var KeyValues: Variant);
begin
  if Assigned(Wizard.OnDestinationLocate) then
    Wizard.OnDestinationLocate(Sender, KeyColumns, Row, KeyFields, KeyValues);
end;

procedure TQImport2WizardF.FormCreate(Sender: TObject);
var
  i: integer;
begin
  pgImport.ActivePage := tsImportType;
  for i := 0 to pgImport.PageCount - 1 do
    pgImport.Pages[i].Parent := Self;

  vwTXT := TQImport2TXTViewer.Create(Self);
  with vwTXT do begin
    Parent := pgImport.Pages[1];
    Height := 281;
    Left := 191;
    Top := 90;
    Width := 372;
    OnChangeSelection := TXTViewerChangeSelection;
    OnDeleteArrow := TXTViewerDeleteArrow;
    OnMoveArrow := TXTViewerMoveArrow;
    OnIntersectArrows := TXTViewerIntersectArrows;
  end;

  paTip := TInfoPanel.Create(Self);
  paTip.AutoSize := false;
  paTip.WordWrap := true;

  bHelp.Enabled := Wizard.ShowHelpButton;
  bHelp.Visible := Wizard.ShowHelpButton;
  btnLoadTemplate.Enabled := Wizard.ShowSaveLoadButtons;
  btnLoadTemplate.Visible := Wizard.ShowSaveLoadButtons;
  btnSaveTemplate.Enabled := Wizard.ShowSaveLoadButtons;
  btnSaveTemplate.Visible := Wizard.ShowSaveLoadButtons;

  laTemplateFileNameTag.Visible :=
    not Wizard.ShowSaveLoadButtons and Wizard.AutoLoadTemplate;
  
  FileName := Wizard.FileName;
  GoToLastPage := Wizard.GoToLastPage;
  AutoSaveTemplate := Wizard.AutoSaveTemplate;
  FieldFormats := Wizard.FieldFormats;

  DataSet := Wizard.DataSet;
  DBGrid := Wizard.DBGrid;
  ListView := Wizard.ListView;
  StringGrid := Wizard.StringGrid;
  FillCombosAndLists;

  TuneOpenDialog;
  ChangeExtension;
  TuneCSVControls;

  rbtXLS.Enabled := aiXLS in Wizard.AllowedImports;
  rbtDBF.Enabled := aiDBF in Wizard.AllowedImports;
  rbtXML.Enabled := aiXML in Wizard.AllowedImports;
  rbtTXT.Enabled := aiTXT in Wizard.AllowedImports;
  rbtCSV.Enabled := aiCSV in Wizard.AllowedImports;

  if rbtXLS.Enabled then rbtXLS.Checked := true
  else if rbtDBF.Enabled then rbtDBF.Checked := true
       else if rbtXML.Enabled then rbtXML.Checked := true
            else if rbtTXT.Enabled then rbtTXT.Checked := true
                 else if rbtCSV.Enabled then rbtCSV.Checked := true;

  FXLSFile := TxlsFile.Create;
  XLSSkipCols := 0;
  XLSSkipRows := 0;

  DBFSkipDeleted := true;

  TXTSkipLines := 0;
  FTXTClearing := false;
  CSVSkipLines := 0;
  XMLWriteOnFly := false; 

  DecimalSeparator := Wizard.Formats.DecimalSeparator;
  ThousandSeparator := Wizard.Formats.ThousandSeparator;
  ShortDateFormat := Wizard.Formats.ShortDateFormat;
  LongDateFormat := Wizard.Formats.LongDateFormat;
  DateSeparator := Wizard.Formats.DateSeparator;
  ShortTimeFormat := Wizard.Formats.ShortTimeFormat;
  LongTimeFormat := Wizard.Formats.LongTimeFormat;
  TimeSeparator := Wizard.Formats.TimeSeparator;

  CommitAfterDone := Wizard.CommitAfterDone;
  CommitRecCount := Wizard.CommitRecCount;
  ImportRecCount := Wizard.ImportRecCount;
  CloseAfterImport := Wizard.CloseAfterImport;
  EnableErrorLog := Wizard.ErrorLog;
  ErrorLogFileName := Wizard.ErrorLogFileName;
  RewriteErrorLogFile := Wizard.RewriteErrorLogFile;
  ShowErrorLog := Wizard.ShowErrorLog;
  chEnableErrorLogClick(nil);

  AddType := Wizard.AddType;
  ImportMode := Wizard.ImportMode;

  Step := 0;
  FTXTItemIndex := -1;
  FCSVItemIndex := -1;
  FNeedLoadFile := true;

  FFormatItem := nil;
  FLoadingFormatItem := false;

  if AutoLoadTemplate then
  begin
    if Assigned(Wizard.OnLoadTemplate) then
      Wizard.OnLoadTemplate(Wizard, TemplateFileName);
    LoadTemplateFromFile(TemplateFileName);
  end;

  if Assigned(Wizard.Picture.Graphic) and not Wizard.Picture.Graphic.Empty then
    Image.Picture := Wizard.Picture;

  FXLSIsEditingGrid := false;
  FXLSGridSelection := TMapRow.Create(nil);
  FXLSDefinedRanges := TMapRow.Create(nil);
end;

procedure TQImport2WizardF.FormDestroy(Sender: TObject);
var
  i: integer;
begin
  FXLSDefinedRanges.Free; 
  FXLSGridSelection.Free;
  FXLSFile.Free;
  
  XLSClearFieldList;
  TXTClearCombo;
  CSVClearCombo;
  DBFClearList;
  DBFClearTableList;
  XMLClearList;
  XMLClearTableList;
  FormatsClearList;

  for i := 0 to pgImport.PageCount - 1 do
    pgImport.Pages[i].Parent := pgImport;
end;

procedure TQImport2WizardF.FormShow(Sender: TObject);
begin
  SetCaptions;
  SetTitle;
end;

procedure TQImport2WizardF.rbtClick(Sender: TObject);
var
  Rbt: TRadioButton;
begin
  if not (Sender is TRadioButton) then Exit; 
  Rbt := (Sender as TRadioButton);
  if Rbt.Name = 'rbtXLS' then ImportType := aiXLS
  else if Rbt.Name = 'rbtDBF' then ImportType := aiDBF
       else if Rbt.Name = 'rbtXML' then ImportType := aiXML
            else if Rbt.Name = 'rbtTXT' then ImportType := aiTXT
                 else if Rbt.Name = 'rbtCSV' then ImportType := aiCSV;
end;

procedure TQImport2WizardF.cbCommaExit(Sender: TObject);
begin
  if AnsiCompareText(cbComma.Text, 'TAB') = 0 then
    Comma := Chr(VK_TAB)
  else if AnsiCompareText(cbComma.Text, 'SPACE') = 0 then
    Comma := Chr(VK_SPACE)
  else Comma := Str2Char(cbComma.Text, Comma);
end;

procedure TQImport2WizardF.cbQuoteExit(Sender: TObject);
begin
  Quote := Str2Char(cbQuote.Text, Quote);
end;

procedure TQImport2WizardF.edtFileNameChange(Sender: TObject);
begin
  FileName := edtFileName.Text
end;

procedure TQImport2WizardF.chGoToLastPageClick(Sender: TObject);
begin
  GoToLastPage := chGoToLastPage.Checked;
  Wizard.GoToLastPage := GoToLastPage;
end;

procedure TQImport2WizardF.chAutoSaveTemplateClick(Sender: TObject);
begin
  AutoSaveTemplate := chAutoSaveTemplate.Checked;
  Wizard.AutoSaveTemplate := AutoSaveTemplate;
end;

procedure TQImport2WizardF.spbBrowseClick(Sender: TObject);
begin
  if opnDialog.Execute then edtFileName.Text := opnDialog.FileName;
end;

procedure TQImport2WizardF.SetImportType(const Value: TAllowedImport);
begin
  if FImportType <> Value then
  begin
    if not (Value in Wizard.AllowedImports) then
      raise EQImportError.Create({$IFDEF WIN32}QImportLoadStr(QIE_UnknownImportSource){$ENDIF}
                                 {$IFDEF LINUX}QIE_UnknownImportSource{$ENDIF});
    FImportType := Value;
    //----
    rbtXLS.Checked := FImportType = aiXLS;
    rbtDBF.Checked := FImportType = aiDBF;
    rbtXML.Checked := FImportType = aiXML;
    rbtTXT.Checked := FImportType = aiTXT;
    rbtCSV.Checked := FImportType = aiCSV;
    //----
    TuneOpenDialog;
    ChangeExtension;
    TuneCSVControls;
    if FImportType = aiCSV then
    begin
      if AnsiCompareText(cbComma.Text, 'TAB') = 0 then
        Comma := Chr(VK_TAB)
      else if AnsiCompareText(cbComma.Text, 'SPACE') = 0 then
        Comma := Chr(VK_SPACE)
      else
        Comma := Str2Char(cbComma.Text, Comma);
      Quote := Str2Char(cbQuote.Text, Quote);
    end;
    TuneButtons;
  end;
end;

procedure TQImport2WizardF.SetFileName(const Value: string);
var
  i: integer;
begin
  if AnsiCompareText(FFileName, Trim(Value)) <> 0 then begin
    FFileName := Trim(Value);
    edtFileName.Text := FFileName;
    //----
    case ImportType of
      aiXLS: begin
        lvXLSRanges.Items.Clear;
        for i := 0 to lvXLSFields.Items.Count - 1 do
          TMapRow(lvXLSFields.Items[i].Data).AsString := EmptyStr;
        XLSClearDataSheets;
        XLSSkipCols := 0;
        XLSSkipRows := 0;
      end;
    end;
    //----
    TuneButtons;
    SetTitle;
    FNeedLoadFile := true;
  end;
end;

procedure TQImport2WizardF.SetGoToLastPage(Value: boolean);
begin
  if FGoToLastPage <> Value then begin
    FGoToLastPage := Value;
    chGoToLastPage.Checked := FGoToLastPage;
  end;
end;

procedure TQImport2WizardF.SetAutoSaveTemplate(Value: boolean);
begin
  if FAutoSaveTemplate <> Value then begin
    FAutoSaveTemplate := Value;
    chAutoSaveTemplate.Checked := FAutoSaveTemplate;
  end;
end;

procedure TQImport2WizardF.SetComma(const Value: char);
var
  i: integer;
begin
  if FComma <> Value then begin
    FComma := Value;
    if FComma = Chr(VK_TAB) then
      cbComma.Text := 'TAB'
    else if FComma = Chr(VK_SPACE) then
      cbComma.Text := 'SPACE'
    else cbComma.Text := Char2Str(FComma);

    for i := 0 to lvCSVFields.Items.Count - 1 do
      lvCSVFields.Items[i].SubItems[0] := EmptyStr;
    if lvCSVFields.Items.Count > 0 then begin
      lvCSVFields.Items[0].Focused := true;
      lvCSVFields.Items[0].Selected := true;
    end;

    FNeedLoadFile := true;
    TuneButtons;
  end;
end;

procedure TQImport2WizardF.SetQuote(const Value: char);
var
  i: integer;
begin
  if FQuote <> Value then begin
    FQuote := Value;
    cbQuote.Text := Char2Str(FQuote);

    for i := 0 to lvCSVFields.Items.Count - 1 do
      lvCSVFields.Items[i].SubItems[0] := EmptyStr;
    if lvCSVFields.Items.Count > 0 then begin
      lvCSVFields.Items[0].Focused := true;
      lvCSVFields.Items[0].Selected := true;
    end;

    FNeedLoadFile := true;
  end;
end;

procedure TQImport2WizardF.FillCombosAndLists;
begin
  XLSFillFieldList;
  TXTFillCombo;
  CSVFillCombo;
  DBFFillList;
  XMLFillList;
  FormatsFillList;
  FillKeyColumns(KeyColumns);
end;

procedure TQImport2WizardF.FillKeyColumns(Strings: TStrings);
var
  i, j: integer;
  str: string;
begin
  lvAvailableColumns.Items.BeginUpdate;
  try
    lvSelectedColumns.Items.BeginUpdate;
    try
      lvAvailableColumns.Items.Clear;
      lvSelectedColumns.Items.Clear;

      for i := 0 to Strings.Count - 1 do begin
        j := QImportDestinationFindColumn(false, ImportDestination, DataSet,
             DBGrid, ListView, StringGrid, GridCaptionRow, Strings[i]);
        if j > -1 then
          lvSelectedColumns.Items.Add.Caption :=
            QImportDestinationColName(false, ImportDestination, DataSet,
              DBGrid, ListView, StringGrid, GridCaptionRow, j);
      end;

      for i := 0 to QImportDestinationColCount(false, ImportDestination,
                      DataSet, DBGrid, ListView, StringGrid) - 1 do begin
         str := QImportDestinationColName(false, ImportDestination, DataSet,
                  DBGrid, ListView, StringGrid, GridCaptionRow, i);
         if Strings.IndexOf(str) = -1 then
           lvAvailableColumns.Items.Add.Caption := str;
      end;
      if lvAvailableColumns.Items.Count > 0 then begin
        lvAvailableColumns.Items[0].Focused := true;
        lvAvailableColumns.Items[0].Selected := true;
      end;
      if lvSelectedColumns.Items.Count > 0 then begin
        lvSelectedColumns.Items[0].Focused := true;
        lvSelectedColumns.Items[0].Selected := true;
      end;
    finally
      lvSelectedColumns.Items.EndUpdate;
    end;
  finally
    lvAvailableColumns.Items.EndUpdate;
  end;
end;

procedure TQImport2WizardF.MoveToSelected(Source, Destination: TListView;
  All: boolean; Index: integer);
var
  List: TStringList;
  i: integer;
  ListItem: TListItem;
begin
  Source.Items.BeginUpdate;
  try
    Destination.Items.BeginUpdate;
    try
      List := TStringList.Create;
      try
        for i := Source.Items.Count - 1 downto 0 do
          if Source.Items[i].Selected or All then begin
            List.Add(Source.Items[i].Caption);
            Source.Items.Delete(i);
          end;
        ListItem := nil;
        if (List.Count = 1) and (Index > -1) then begin
          ListItem := Destination.Items.Insert(Index);
          ListItem.Caption := List[0];
          List.Delete(0);
        end
        else
          for i := List.Count - 1 downto 0 do begin
            ListItem := Destination.Items.Add;
            ListItem.Caption := List[i];
            List.Delete(i);
          end;
      finally
        List.Free;
      end;
      if Assigned(Source.ItemFocused) then
        Source.ItemFocused.Selected := true;
      if Assigned(ListItem) then
        for i := 0 to Destination.Items.Count - 1 do
          Destination.Items[i].Selected := Destination.Items[i] = ListItem;
    finally
      Destination.Items.EndUpdate;
    end;
  finally
    Source.Items.EndUpdate;
  end;
end;

procedure TQImport2WizardF.SetCaptions;
var
  N: integer;
begin
  grpImportTypes.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ImportFrom){$ENDIF}
                            {$IFDEF LINUX}QIW_ImportFrom{$ENDIF};
  rbtXLS.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XLS){$ENDIF}
                    {$IFDEF LINUX}QIW_XLS{$ENDIF};
  rbtDBF.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DBF){$ENDIF}
                    {$IFDEF LINUX}QIW_DBF{$ENDIF};
  rbtXML.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XML){$ENDIF}
                    {$IFDEF LINUX}QIW_XML{$ENDIF};
  rbtTXT.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TXT){$ENDIF}
                    {$IFDEF LINUX}QIW_TXT{$ENDIF};
  rbtCSV.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CSV){$ENDIF}
                    {$IFDEF LINUX}QIW_CSV{$ENDIF};
  laComma.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Comma){$ENDIF}
                     {$IFDEF LINUX}QIW_Comma{$ENDIF};
  laQuote.Caption := QImportLoadStr(QIW_Quote);
  laSourceFileName.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_FileName){$ENDIF}
                              {$IFDEF LINUX}QIW_FileName{$ENDIF};
  laTemplateFileNameTag.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TemplateFileName){$ENDIF}
                                   {$IFDEF LINUX}QIW_TemplateFileName{$ENDIF}; ;
  odTemplate.Filter := {$IFDEF WIN32}QImportLoadStr(QIF_TEMPLATE){$ENDIF}
                       {$IFDEF LINUX}QIF_TEMPLATE{$ENDIF};
  bHelp.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Help){$ENDIF}
                   {$IFDEF LINUX}QIW_Help{$ENDIF};
  bBack.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Back){$ENDIF}
                   {$IFDEF LINUX}QIW_Back{$ENDIF};
  bNext.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Next){$ENDIF}
                   {$IFDEF LINUX}QIW_Next{$ENDIF};
  bCancel.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Cancel){$ENDIF}
                     {$IFDEF LINUX}QIW_Cancel{$ENDIF};
  bOk.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Execute){$ENDIF}
                 {$IFDEF LINUX}QIW_Execute{$ENDIF};
  gbTemplateOptions.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TemplateOptions){$ENDIF}
                               {$IFDEF LINUX}QIW_TemplateOptions{$ENDIF};
  chGoToLastPage.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_GoToLastPage){$ENDIF}
                            {$IFDEF LINUX}QIW_GoToLastPage{$ENDIF};
  chAutoSaveTemplate.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_AutoSaveTemplate){$ENDIF}
                                {$IFDEF LINUX}QIW_AutoSaveTemplate{$ENDIF};
  btnLoadTemplate.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_LoadTemplate){$ENDIF}
                             {$IFDEF LINUX}QIW_LoadTemplate{$ENDIF};
  //-----
  lvTXTFields.Columns[0].Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TXT_Fields){$ENDIF}
                                    {$IFDEF LINUX}QIW_TXT_Fields{$ENDIF};
  lvTXTFields.Columns[1].Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TXT_Fields_Pos){$ENDIF}
                                    {$IFDEF LINUX}QIW_TXT_Fields_Pos{$ENDIF};
  lvTXTFields.Columns[2].Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TXT_Fields_Size){$ENDIF}
                                    {$IFDEF LINUX}QIW_TXT_Fields_Size{$ENDIF};
  tbtTXTClear.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_TXT_Clear){$ENDIF}
                      {$IFDEF LINUX}QIW_TXT_Clear{$ENDIF};
  laTXTSkipLines.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TXT_SkipLines){$ENDIF}
                            {$IFDEF LINUX}QIW_TXT_SkipLines{$ENDIF};
  //-----
  lvCSVFields.Columns[0].Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CSV_Fields){$ENDIF}
                                    {$IFDEF LINUX}QIW_CSV_Fields{$ENDIF};
  laCSVColNumber.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CSV_ColNumber){$ENDIF}
                            {$IFDEF LINUX}QIW_CSV_ColNumber{$ENDIF};
  laCSVSkipLines.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CSV_SkipLines){$ENDIF}
                            {$IFDEF LINUX}QIW_CSV_SkipLines{$ENDIF};
  tbtCSVAutoFill.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_CSV_AutoFill){$ENDIF}
                         {$IFDEF LINUX}QIW_CSV_AutoFill{$ENDIF};
  tbtCSVClear.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_CSV_Clear){$ENDIF}
                      {$IFDEF LINUX}QIW_CSV_Clear{$ENDIF};
  //-----
  bDBFAdd.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DBF_Add){$ENDIF}
                     {$IFDEF LINUX}QIW_DBF_Add{$ENDIF};
  bDBFAutoFill.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DBF_AutoFill){$ENDIF}
                          {$IFDEF LINUX}QIW_DBF_AutoFill{$ENDIF};
  bDBFRemove.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DBF_Remove){$ENDIF}
                        {$IFDEF LINUX}QIW_DBF_Remove{$ENDIF};
  bDBFClear.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DBF_Clear){$ENDIF}
                       {$IFDEF LINUX}QIW_DBF_Clear{$ENDIF};
  chDBFSkipDeleted.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DBF_SkipDeleted){$ENDIF}
                              {$IFDEF LINUX}QIW_DBF_SkipDeleted{$ENDIF};
  //-----
  bXMLAdd.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XML_Add){$ENDIF}
                     {$IFDEF LINUX}QIW_XML_Add{$ENDIF};
  bXMLAutoFill.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XML_AutoFill){$ENDIF}
                          {$IFDEF LINUX}QIW_XML_AutoFill{$ENDIF};
  bXMLRemove.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XML_Remove){$ENDIF}
                        {$IFDEF LINUX}QIW_XML_Remove{$ENDIF};
  bXMLClear.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XML_Clear){$ENDIF}
                       {$IFDEF LINUX}QIW_XML_Clear{$ENDIF};
  chXMLWriteOnFly.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XML_WriteOnFly){$ENDIF}
                             {$IFDEF LINUX}QIW_XML_WriteOnFly{$ENDIF};
  //-----
  lvXLSFields.Columns[0].Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_Fields){$ENDIF}
                                    {$IFDEF LINUX}QIW_XLS_Fields{$ENDIF};
  lvXLSRanges.Columns[0].Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_Ranges){$ENDIF}
                                    {$IFDEF LINUX}QIW_XLS_Ranges{$ENDIF};
  tbtXLSAddRange.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_AddRange){$ENDIF}
                         {$IFDEF LINUX}QIW_XLS_AddRange{$ENDIF};
  tbtXLSEditRange.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_EditRange){$ENDIF}
                          {$IFDEF LINUX}QIW_XLS_EditRange{$ENDIF};
  tbtXLSDelRange.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_DelRange){$ENDIF}
                         {$IFDEF LINUX}QIW_XLS_DelRange{$ENDIF};
  tbtXLSMoveRangeUp.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_MoveRangeUp){$ENDIF}
                            {$IFDEF LINUX}QIW_XLS_MoveRangeUp{$ENDIF};
  tbtXLSMoveRangeDown.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_MoveRangeDown){$ENDIF}
                              {$IFDEF LINUX}QIW_XLS_MoveRangeDown{$ENDIF};
  laXLSSkipCols.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_SkipCols){$ENDIF}
                           {$IFDEF LINUX}QIW_XLS_SkipCols{$ENDIF};
  laXLSSkipRows.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_SkipRows){$ENDIF}
                           {$IFDEF LINUX}QIW_XLS_SkipRows{$ENDIF};
  tbtXLSAutoFillCols.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_AutoFillCols){$ENDIF}
                             {$IFDEF LINUX}QIW_XLS_AutoFillCols{$ENDIF};
  tbtXLSAutoFillRows.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_AutoFillRows){$ENDIF}
                             {$IFDEF LINUX}QIW_XLS_AutoFillRows{$ENDIF};
  tbtXLSClearFieldRanges.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_ClearFieldRanges){$ENDIF}
                                 {$IFDEF LINUX}QIW_XLS_ClearFieldRanges{$ENDIF};
  tbtXLSClearAllRanges.Hint := {$IFDEF WIN32}QImportLoadStr(QIW_XLS_ClearAllRanges){$ENDIF}
                               {$IFDEF LINUX}QIW_XLS_ClearAllRanges{$ENDIF};
  //-----
  tshBaseFormats.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_BaseFormats){$ENDIF}
                            {$IFDEF LINUX}QIW_BaseFormats{$ENDIF};
  grpDateTimeFormats.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DateTimeFormats){$ENDIF}
                                {$IFDEF LINUX}QIW_DateTimeFormats{$ENDIF};
  grpSeparators.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Separators){$ENDIF}
                           {$IFDEF LINUX}QIW_Separators{$ENDIF};
  laDecimalSeparator.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DecimalSeparator){$ENDIF}
                                {$IFDEF LINUX}QIW_DecimalSeparator{$ENDIF};
  laThousandSeparator.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ThousandSeparator){$ENDIF}
                                 {$IFDEF LINUX}QIW_ThousandSeparator{$ENDIF};
  laShortDateFormat.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ShortDateFormat){$ENDIF}
                               {$IFDEF LINUX}QIW_ShortDateFormat{$ENDIF};
  laLongDateFormat.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_LongDateFormat){$ENDIF}
                              {$IFDEF LINUX}QIW_LongDateFormat{$ENDIF};
  laDateSeparator.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_DateSeparator){$ENDIF}
                             {$IFDEF LINUX}QIW_DateSeparator{$ENDIF};
  laShortTimeFormat.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ShortTimeFormat){$ENDIF}
                               {$IFDEF LINUX}QIW_ShortTimeFormat{$ENDIF};
  laLongTimeFormat.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_LongTimeFormat){$ENDIF}
                              {$IFDEF LINUX}QIW_LongTimeFormat{$ENDIF};
  laTimeSeparator.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_TimeSeparator){$ENDIF}
                             {$IFDEF LINUX}QIW_TimeSeparator{$ENDIF};

  laBooleanTrue.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_BooleanTrue){$ENDIF}
                           {$IFDEF LINUX}QIW_BooleanTrue{$ENDIF};
  mmBooleanTrue.Lines.Assign(Wizard.Formats.BooleanTrue);
  laBooleanFalse.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_BooleanFalse){$ENDIF}
                            {$IFDEF LINUX}QIW_BooleanFalse{$ENDIF};
  mmBooleanFalse.Lines.Assign(Wizard.Formats.BooleanFalse);
  laNullValues.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_NullValue){$ENDIF}
                          {$IFDEF LINUX}QIW_NullValue{$ENDIF};
  mmNullValues.Lines.Assign(Wizard.Formats.NullValues);
  //-----------------------
  tshDataFormats.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_Caption){$ENDIF}
                            {$IFDEF LINUX}QIWDF_Caption{$ENDIF};
  lstFormatFields.Columns[0].Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_Fields){$ENDIF}
                                        {$IFDEF LINUX}QIWDF_Fields{$ENDIF};
  tsFieldTuning.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_Tuning){$ENDIF}
                           {$IFDEF LINUX}QIWDF_Tuning{$ENDIF};
  laGeneratorValue.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_GeneratorValue){$ENDIF}
                              {$IFDEF LINUX}QIWDF_GeneratorValue{$ENDIF};
  laGeneratorStep.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_GeneratorStep){$ENDIF}
                             {$IFDEF LINUX}QIWDF_GeneratorStep{$ENDIF};
  laConstantValue.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_ConstantValue){$ENDIF}
                             {$IFDEF LINUX}QIWDF_ConstantValue{$ENDIF};
  laNullValue.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_NullValue){$ENDIF}
                         {$IFDEF LINUX}QIWDF_NullValue{$ENDIF};
  laDefaultValue.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_DefaultValue){$ENDIF}
                            {$IFDEF LINUX}QIWDF_DefaultValue{$ENDIF};
  laLeftQuote.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_LeftQuote){$ENDIF}
                         {$IFDEF LINUX}QIWDF_LeftQuote{$ENDIF};
  laRightQuote.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_RightQuote){$ENDIF}
                          {$IFDEF LINUX}QIWDF_RightQuote{$ENDIF};
  laQuoteAction.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_QuoteAction){$ENDIF}
                           {$IFDEF LINUX}QIWDF_QuoteAction{$ENDIF};
  N := cmbQuoteAction.ItemIndex;
  cmbQuoteAction.Items[0] := {$IFDEF WIN32}QImportLoadStr(QIWDF_QuoteNone){$ENDIF}
                             {$IFDEF LINUX}QIWDF_QuoteNone{$ENDIF};
  cmbQuoteAction.Items[1] := {$IFDEF WIN32}QImportLoadStr(QIWDF_QuoteAdd){$ENDIF}
                             {$IFDEF LINUX}QIWDF_QuoteAdd{$ENDIF};
  cmbQuoteAction.Items[2] := {$IFDEF WIN32}QImportLoadStr(QIWDF_QuoteRemove){$ENDIF}
                             {$IFDEF LINUX}QIWDF_QuoteRemove{$ENDIF};
  cmbQuoteAction.ItemIndex := N;
  laCharCase.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharCase){$ENDIF}
                        {$IFDEF LINUX}QIWDF_CharCase{$ENDIF};
  laCharSet.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharSet){$ENDIF}
                       {$IFDEF LINUX}QIWDF_CharSet{$ENDIF};
  N := cmbCharCase.ItemIndex;
  cmbCharCase.Items[0] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharCaseNone){$ENDIF}
                          {$IFDEF LINUX}QIWDF_CharCaseNone{$ENDIF};
  cmbCharCase.Items[1] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharCaseUpper){$ENDIF}
                          {$IFDEF LINUX}QIWDF_CharCaseUpper{$ENDIF};
  cmbCharCase.Items[2] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharCaseLower){$ENDIF}
                          {$IFDEF LINUX}QIWDF_CharCaseLower{$ENDIF};
  cmbCharCase.Items[3] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharCaseUpperFirst){$ENDIF}
                          {$IFDEF LINUX}QIWDF_CharCaseUpperFirst{$ENDIF};
  cmbCharCase.Items[4] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharCaseUpperWord){$ENDIF}
                          {$IFDEF LINUX}QIWDF_CharCaseUpperWord{$ENDIF};
  cmbCharCase.ItemIndex := N;
  N := cmbCharSet.ItemIndex;
  cmbCharSet.Items[0] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharSetNone){$ENDIF}
                         {$IFDEF LINUX}QIWDF_CharSetNone{$ENDIF};
  cmbCharSet.Items[1] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharSetAnsi){$ENDIF}
                         {$IFDEF LINUX}QIWDF_CharSetAnsi{$ENDIF};
  cmbCharSet.Items[2] := {$IFDEF WIN32}QImportLoadStr(QIWDF_CharSetOem){$ENDIF}
                         {$IFDEF LINUX}QIWDF_CharSetOem{$ENDIF};
  cmbCharSet.ItemIndex := N;
  laReplacements.Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_Replacements){$ENDIF}
                            {$IFDEF LINUX}QIWDF_Replacements{$ENDIF};
  lvReplacements.Columns[0].Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_TextToFind){$ENDIF}
                                       {$IFDEF LINUX}QIWDF_TextToFind{$ENDIF};
  lvReplacements.Columns[1].Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_ReplaceWith){$ENDIF}
                                       {$IFDEF LINUX}QIWDF_ReplaceWith{$ENDIF};
  lvReplacements.Columns[2].Caption := {$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase){$ENDIF}
                                       {$IFDEF LINUX}QIWDF_IgnoreCase{$ENDIF};
  tbtAddReplacement.Hint := {$IFDEF WIN32}QImportLoadStr(QIWDF_AddReplacement){$ENDIF}
                            {$IFDEF LINUX}QIWDF_AddReplacement{$ENDIF};
  tbtEditReplacement.Hint := {$IFDEF WIN32}QImportLoadStr(QIWDF_EditReplacement){$ENDIF}
                             {$IFDEF LINUX}QIWDF_EditReplacement{$ENDIF};
  tbtDelReplacement.Hint := {$IFDEF WIN32}QImportLoadStr(QIWDF_DelReplacement){$ENDIF}
                            {$IFDEF LINUX}QIWDF_DelReplacement{$ENDIF};
  //-----------------------
  tshCommit.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CommitOptions){$ENDIF}
                       {$IFDEF LINUX}QIW_CommitOptions{$ENDIF};
  grpCommit.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Commit){$ENDIF}
                       {$IFDEF LINUX}QIW_Commit{$ENDIF};
  chCommitAfterDone.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CommitAfterDone){$ENDIF}
                               {$IFDEF LINUX}QIW_CommitAfterDone{$ENDIF};
  laCommitRecCount_01.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CommitRecCount){$ENDIF}
                                 {$IFDEF LINUX}QIW_CommitRecCount{$ENDIF};
  laCommitRecCount_02.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Records){$ENDIF}
                                 {$IFDEF LINUX}QIW_Records{$ENDIF};

  grpImportCount.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_RecordCount){$ENDIF}
                            {$IFDEF LINUX}QIW_RecordCount{$ENDIF};
  chImportAllRecords.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ImportAllRecords){$ENDIF}
                                {$IFDEF LINUX}QIW_ImportAllRecords{$ENDIF};
  laImportRecCount_01.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ImportRecCount){$ENDIF}
                                 {$IFDEF LINUX}QIW_ImportRecCount{$ENDIF};
  laImportRecCount_02.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_Records){$ENDIF}
                                 {$IFDEF LINUX}QIW_Records{$ENDIF};
  chCloseAfterImport.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_CloseAfterImport){$ENDIF}
                                {$IFDEF LINUX}QIW_CloseAfterImport{$ENDIF};

  grpErrorLog.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ErrorLog){$ENDIF}
                         {$IFDEF LINUX}QIW_ErrorLog{$ENDIF};
  chEnableErrorLog.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_EnableErrorLog){$ENDIF}
                              {$IFDEF LINUX}QIW_EnableErrorLog{$ENDIF};
  laErrorLogFileName.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ErrorLogFileName){$ENDIF}
                                {$IFDEF LINUX}QIW_ErrorLogFileName{$ENDIF};
  chRewriteErrorLogFile.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_RewriteErrorLogFile){$ENDIF}
                                   {$IFDEF LINUX}QIW_RewriteErrorLogFile{$ENDIF};
  chShowErrorLog.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ShowErrorLog){$ENDIF}
                            {$IFDEF LINUX}QIW_ShowErrorLog{$ENDIF};
  btnSaveTemplate.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_SaveTemplate){$ENDIF}
                             {$IFDEF LINUX}QIW_SaveTemplate{$ENDIF};

  tshAdvanced.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ImportAdvanced){$ENDIF}
                         {$IFDEF LINUX}QIW_ImportAdvanced{$ENDIF};
  rgAddType.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_AddType){$ENDIF}
                       {$IFDEF LINUX}QIW_AddType{$ENDIF};
  N := rgAddType.ItemIndex;
  rgAddType.Items[0] := {$IFDEF WIN32}QImportLoadStr(QIW_AddType_Append){$ENDIF}
                        {$IFDEF LINUX}QIW_AddType_Append{$ENDIF};
  rgAddType.Items[1] := {$IFDEF WIN32}QImportLoadStr(QIW_AddType_Insert){$ENDIF}
                        {$IFDEF LINUX}QIW_AddType_Insert{$ENDIF};
  rgAddType.ItemIndex := N;

  rgImportMode.Caption := {$IFDEF WIN32}QImportLoadStr(QIWIM_Caption){$ENDIF}
                          {$IFDEF LINUX}QIWIM_Caption{$ENDIF};
  N := rgImportMode.ItemIndex;
  rgImportMode.Items[0] := {$IFDEF WIN32}QImportLoadStr(QIWIM_Insert_All){$ENDIF}
                           {$IFDEF LINUX}QIWIM_Insert_All{$ENDIF};
  rgImportMode.Items[1] := {$IFDEF WIN32}QImportLoadStr(QIWIM_Insert_New){$ENDIF}
                           {$IFDEF LINUX}QIWIM_Insert_New{$ENDIF};
  rgImportMode.Items[2] := {$IFDEF WIN32}QImportLoadStr(QIWIM_Update){$ENDIF}
                           {$IFDEF LINUX}QIWIM_Update{$ENDIF};
  rgImportMode.Items[3] := {$IFDEF WIN32}QImportLoadStr(QIWIM_Update_or_Insert){$ENDIF}
                           {$IFDEF LINUX}QIWIM_Update_or_Insert{$ENDIF};
  rgImportMode.Items[4] := {$IFDEF WIN32}QImportLoadStr(QIWIM_Delete){$ENDIF}
                           {$IFDEF LINUX}QIWIM_Delete{$ENDIF};
  rgImportMode.Items[5] := {$IFDEF WIN32}QImportLoadStr(QIWIM_Delete_or_Insert){$ENDIF}
                           {$IFDEF LINUX}QIWIM_Delete_or_Insert{$ENDIF};
  rgImportMode.ItemIndex := N;

  laAvailableColumns.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_AvailableColumns){$ENDIF}
                                {$IFDEF LINUX}QIW_AvailableColumns{$ENDIF};
  laSelectedColumns.Caption := {$IFDEF WIN32}QImportLoadStr(QIW_SelectedColumns){$ENDIF}
                               {$IFDEF LINUX}QIW_SelectedColumns{$ENDIF};
end;

procedure TQImport2WizardF.TuneOpenDialog;
begin
  case FImportType of
    aiXLS: opnDialog.Filter := {$IFDEF WIN32}QImportLoadStr(QIF_XLS){$ENDIF}
                               {$IFDEF LINUX}QIF_XLS{$ENDIF};
    aiDBF: opnDialog.Filter := {$IFDEF WIN32}QImportLoadStr(QIF_DBF){$ENDIF}
                               {$IFDEF LINUX}QIF_DBF{$ENDIF};
    aiXML: opnDialog.Filter := {$IFDEF WIN32}QImportLoadStr(QIF_XML){$ENDIF}
                               {$IFDEF LINUX}QIF_XML{$ENDIF};
    aiTXT: opnDialog.Filter := {$IFDEF WIN32}QImportLoadStr(QIF_TXT){$ENDIF}
                               {$IFDEF LINUX}QIF_TXT{$ENDIF};
    aiCSV: opnDialog.Filter := {$IFDEF WIN32}QImportLoadStr(QIF_CSV){$ENDIF}
                               {$IFDEF LINUX}QIF_CSV{$ENDIF};
  end;
end;

procedure TQImport2WizardF.ChangeExtension;
begin
  if not Wizard.AutoChangeExtension then Exit;
  if Trim(FileName) = EmptyStr then Exit;
  FileName := ChangeFileExt(FileName, FileExts[Ord(FImportType)]);
end;

procedure TQImport2WizardF.TuneCSVControls;
begin
  laComma.Enabled := FImportType = aiCSV;
  cbComma.Enabled := FImportType = aiCSV;
  if cbComma.Enabled  and (cbComma.Text = EmptyStr) then
    Comma := GetListSeparator;
  laQuote.Enabled := FImportType = aiCSV;
  cbQuote.Enabled := FImportType = aiCSV;
  if cbQuote.Enabled  and (cbQuote.Text = EmptyStr) then
    Quote := '"';
end;

function TQImport2WizardF.GetWizard: TQImport2Wizard;
begin
  Result := Owner as TQImport2Wizard;
end;

function TQImport2WizardF.GetTemplateFileName: string;
begin
  Result := Wizard.TemplateFileName;
end;

function TQImport2WizardF.GetAutoLoadTemplate: boolean;
begin
  Result := Wizard.AutoLoadTemplate;
end;

function TQImport2WizardF.GetImportDestination: TQImportDestination;
begin
  Result := Wizard.ImportDestination;
end;

function TQImport2WizardF.GetGridCaptionRow: integer;
begin
  Result := Wizard.GridCaptionRow;
end;

function TQImport2WizardF.GetGridStartRow: integer;
begin
  Result := Wizard.GridStartRow;
end;

function TQImport2WizardF.GetKeyColumns: TStrings;
begin
  Result := Wizard.KeyColumns;
end;

procedure TQImport2WizardF.SetStep(const Value: integer);
begin
  if FStep <> Value then
  begin
    if Value = 1 then
    begin
      if not FileExists(FFileName) then
        raise EQImportError.CreateFmt({$IFDEF WIN32}QImportLoadStr(QIE_FileNotExists){$ENDIF}
                                      {$IFDEF LINUX}QIE_FileNotExists{$ENDIF}, [FFileName]);

      if not AllowedImportFileType(FFileName) then
        raise EQImportError.CreateFmt({$IFDEF WIN32}QImportLoadStr(QIE_WrongFileType){$ENDIF}
                                      {$IFDEF LINUX}QIE_WrongFileType{$ENDIF}, [ImportTypeStr(ImportType)]);

      if not ImportTypeEquivFileType(FFileName) then
        raise EQImportError.CreateFmt({$IFDEF WIN32}QImportLoadStr(QIE_WrongFileType){$ENDIF}
                                      {$IFDEF LINUX}QIE_WrongFileType{$ENDIF}, [ImportTypeStr(ImportType)]);

      if not QImportIsDestinationActive(false, ImportDestination, DataSet,
               DBGrid, ListView, StringGrid) then
        raise EQImportError.Create({$IFDEF WIN32}QImportLoadStr(QIE_DataSetClosed){$ENDIF}
                                   {$IFDEF LINUX}QIE_DataSetClosed{$ENDIF});
    end;
    FStep := Value;
    case Value of
      0: TuneStart;
      1: try
        case FImportType of
          aiXLS: XLSTune;
          aiDBF: DBFTune;
          aiXML: XMLTune;
          aiTXT: TXTTune;
          aiCSV: CSVTune;
        end;
      except
        Step := 0;
        raise;
      end;
      2: TuneFormats;
      3: TuneFinish;
    end;
  end;
end;

procedure TQImport2WizardF.ShowTip(Parent: TWinControl; Left, Top, Height,
  Width: integer; const Tip: string);
begin
  paTip.Parent := Parent;
  paTip.Left := Left;
  paTip.Top := Top;
  paTip.Height := Height;
  paTip.Width := Width;
  paTip.Caption := Tip;
end;

procedure TQImport2WizardF.bNextClick(Sender: TObject);
begin
  Step := Step + 1;
end;

procedure TQImport2WizardF.bBackClick(Sender: TObject);
begin
  Step := Step - 1;
end;

procedure TQImport2WizardF.bDBFAddClick(Sender: TObject);
begin
  with lstDBFMap.Items.Add do begin
    Caption := lstDBFDataSet.Selected.Caption;
    SubItems.Add('=');
    SubItems.Add(lstDBF.Selected.Caption);
    Focused := true;
    Selected := true;
  end;
  lstDBFDataSet.Items.Delete(lstDBFDataSet.Selected.Index);
  if lstDBFDataSet.Items.Count > 0 then begin
    lstDBFDataSet.Items[0].Focused := true;
    lstDBFDataSet.Items[0].Selected := true;
  end;
  if lstDBFMap.Items.Count > 0 then begin
    lstDBFMap.Items[0].Focused := true;
    lstDBFMap.Items[0].Selected := true;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.bDBFAutoFillClick(Sender: TObject);
var
  i, N: integer;
begin
  lstDBFDataSet.Items.BeginUpdate;
  try
    lstDBF.Items.BeginUpdate;
    try
      lstDBFMap.Items.BeginUpdate;
      try
        lstDBFMap.Items.Clear;
        DBFClearList;
        DBFFillList;
        N := lstDBF.Items.Count;
        if N > lstDBFDataSet.Items.Count
          then N := lstDBFDataSet.Items.Count;
        for i := N - 1 downto 0 do begin
          with lstDBFMap.Items.Insert(0) do begin
            Caption := lstDBFDataSet.Items[i].Caption;
            SubItems.Add('=');
            SubItems.Add(lstDBF.Items[i].Caption);
          end;
          lstDBFDataSet.Items[i].Delete;
        end;
        if lstDBFMap.Items.Count > 0 then begin
          lstDBFMap.Items[0].Focused := true;
          lstDBFMap.Items[0].Selected := true;
        end;
      finally
        lstDBFMap.Items.EndUpdate;
      end;
    finally
      lstDBF.Items.EndUpdate;
    end;
  finally
    lstDBFDataSet.Items.EndUpdate;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.bDBFRemoveClick(Sender: TObject);
begin
  lstDBFDataSet.Items.Add.Caption := lstDBFMap.Selected.Caption;
  lstDBFMap.Items.Delete(lstDBFMap.Selected.Index);
  if lstDBFMap.Items.Count > 0 then begin
    lstDBFMap.Items[0].Focused := true;
    lstDBFMap.Items[0].Selected := true;
  end;
  if lstDBFDataSet.Items.Count > 0 then begin
    lstDBFDataSet.Items[0].Focused := true;
    lstDBFDataSet.Items[0].Selected := true;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.bDBFClearClick(Sender: TObject);
begin
  lstDBFDataSet.Items.BeginUpdate;
  try
    lstDBFMap.Items.BeginUpdate;
    try
      lstDBFMap.Items.Clear;
      DBFClearList;
      DBFFillList;
    finally
      lstDBFMap.Items.EndUpdate;
    end;
  finally
    lstDBFDataSet.Items.EndUpdate;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (FImportType = aiXLS) and (Step = 1) then FShift := Shift;
end;

procedure TQImport2WizardF.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (FImportType = aiXLS) and (Step = 1) then FShift := [];
end;

procedure TQImport2WizardF.TuneFinish;
begin
  pgImport.ActivePage := tsCommitOptions;
  laStep_02.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                              {$IFDEF LINUX}QIW_Step{$ENDIF}, [3,3]);
  bOk.Enabled := true;
  TuneButtons;
end;

procedure TQImport2WizardF.TuneButtons;
begin
  case Step of
    0: bNext.Enabled := StartReady;
    1: case FImportType of
         aiXLS: begin
           bNext.Enabled := XLSReady;
           tbtXLSAddRange.Enabled := Assigned(lvXLSFields.ItemFocused);
           tbtXLSEditRange.Enabled := Assigned(lvXLSFields.ItemFocused) and
                                      Assigned(lvXLSRanges.ItemFocused);
           tbtXLSDelRange.Enabled := Assigned(lvXLSFields.ItemFocused) and
                                     (lvXLSRanges.SelCount > 0);
           tbtXLSMoveRangeUp.Enabled := Assigned(lvXLSFields.ItemFocused) and
                                        Assigned(lvXLSRanges.ItemFocused) and
                                        (lvXLSRanges.ItemFocused.Index > 0);
           tbtXLSMoveRangeDown.Enabled := Assigned(lvXLSFields.ItemFocused) and
                                          Assigned(lvXLSRanges.ItemFocused) and
                                          (lvXLSRanges.ItemFocused.Index < lvXLSRanges.Items.Count - 1);
         end;
         aiDBF: begin
           bNext.Enabled := DBFReady;
           bDBFAdd.Enabled := Assigned(lstDBFDataSet.Selected) and
                              Assigned(lstDBF.Selected);
           bDBFRemove.Enabled := Assigned(lstDBFMap.Selected);
           bDBFClear.Enabled := lstDBFMap.Items.Count > 0;
         end;
         aiXML: begin
           bNext.Enabled := XMLReady;
           bXMLAdd.Enabled := Assigned(lvXMLDataSet.Selected) and
                              Assigned(lvXML.Selected);
           bXMLRemove.Enabled := Assigned(lvXMLMap.Selected);
           bXMLClear.Enabled := lvXMLMap.Items.Count > 0;
         end;
         aiTXT: bNext.Enabled := TXTReady;
         aiCSV: bNext.Enabled := CSVReady;
       end;
    2: begin
      bNext.Enabled := true;
      tbtAddReplacement.Enabled := Assigned(lstFormatFields.ItemFocused);
      tbtEditReplacement.Enabled := Assigned(lstFormatFields.ItemFocused) and
                                    Assigned(lvReplacements.ItemFocused) ;
      tbtDelReplacement.Enabled := Assigned(lstFormatFields.ItemFocused) and
                                   Assigned(lvReplacements.ItemFocused) ;
    end;
    3: bNext.Enabled := false;
  end;
  bBack.Enabled := Step in [1,2,3];
  bOk.Enabled := ((Step = 1) and (((ImportType = aiXLS) and XLSReady) or
                                  ((ImportType = aiDBF) and DBFReady) or
                                  ((ImportType = aiXML) and XMLReady) or
                                  ((ImportType = aiTXT) and TXTReady) or
                                  ((ImportType = aiCSV) and CSVReady))) or
                 (Step > 1);
end;

function TQImport2WizardF.DBFReady: boolean;
begin
  Result := lstDBFMap.Items.Count > 0;
end;

function TQImport2WizardF.StartReady: boolean;
begin
  Result := ((FImportType = aiCSV) and (FComma <> #0) and
             (FFileName <> EmptyStr)) or
            ((FImportType <> aiCSV) and (FFileName <> EmptyStr));
end;

procedure TQImport2WizardF.TuneStart;
begin
  pgImport.ActivePage := tsImportType;
  TuneButtons;
end;

procedure TQImport2WizardF.bCancelClick(Sender: TObject);
begin
  Close;
end;

procedure TQImport2WizardF.bOkClick(Sender: TObject);
var
  i: integer;
  fileDir: string;
begin
  case FImportType of
    aiXLS: Import := impXLS;
    aiDBF: Import := impDBF;
    aiXML: Import := impXML;
    aiTXT,
    aiCSV: Import := impASCII;
    else Import := nil;
  end;
  if Wizard.ShowProgress then
  begin
    FProgress := TfmQImport2ProgressDlg.CreateProgress(Self, Import);
    FProgress.Show;
    PostMessage(FProgress.Handle, WM_QIMPORT_PROGRESS, QIP_STATE, 0);
    Application.ProcessMessages;
  end;
  try
    Import.DataSet := DataSet;
    Import.DBGrid := DBGrid;
    Import.ListView := ListView;
    Import.StringGrid := StringGrid;

    Import.ImportDestination := ImportDestination;
    Import.GridCaptionRow := GridCaptionRow;
    Import.GridStartRow := GridStartRow;

    Import.FileName := FileName;

    if Assigned(FProgress) then
      FProgress.Errors := Import.Errors;

    if Import is TQImport2DBF then
      with Import as TQImport2DBF do
      begin
        SkipDeleted := DBFSkipDeleted;
      end;

    if Import is TQImport2XML then
      with Import as TQImport2XML do
      begin
        WriteOnFly := XMLWriteOnFly;
      end;

    if Import is TQImport2ASCII then
      with Import as TQImport2ASCII do
      begin
        Quote := Self.Quote;
        Comma := Self.Comma;
        SkipFirstRows := TXTSkipLines * Integer(aiTXT = ImportType) +
                         CSVSkipLines * Integer(aiCSV = ImportType);
      end;

    if Import is TQImport2XLS then
      with Import as TQImport2XLS do
      begin
        SkipFirstRows := Self.XLSSkipRows;
        SkipFirstCols := Self.XLSSkipCOls;
      end;

    TuneMap;
    Import.KeyColumns.Clear;
    for i := 0 to lvSelectedColumns.Items.Count - 1 do
      Import.KeyColumns.Add(lvSelectedColumns.Items[i].Caption);

    with Import.Formats do
    begin
      DecimalSeparator := Self.DecimalSeparator;
      ThousandSeparator := Self.ThousandSeparator;
      ShortDateFormat := Self.ShortDateFormat;
      LongDateFormat := Self.LongDateFormat;
      DateSeparator := Self.DateSeparator;
      ShortTimeFormat := Self.ShortTimeFormat;
      LongTimeFormat := Self.LongTimeFormat;
      TimeSeparator := Self.TimeSeparator;

      BooleanTrue.Assign(mmBooleanTrue.Lines);
      BooleanFalse.Assign(mmBooleanFalse.Lines);
      NullValues.Assign(mmNullValues.Lines);
    end;

    ApplyDataFormats(Import);

    Import.CommitAfterDone := CommitAfterDone;
    Import.CommitRecCount := CommitRecCount;
    Import.ImportRecCount := ImportRecCount * Integer(not chImportAllRecords.Checked);
    Import.ErrorLog := EnableErrorLog;

    fileDir := ExtractFileDir(ErrorLogFileName);
    if fileDir <> '' then
    begin
      if DirExists(fileDir) then
        Import.ErrorLogFileName := ErrorLogFileName
      else
        Import.ErrorLogFileName := ExtractFilePath(Application.ExeName) + ErrorLogFileName;
    end
    else
      Import.ErrorLogFileName := ExtractFilePath(Application.ExeName) + ErrorLogFileName;

    Import.RewriteErrorLogFile := RewriteErrorLogFile;
    Import.ShowErrorLog := ShowErrorLog;

    Import.ImportMode := ImportMode;
    Import.AddType := AddType;

    Import.Execute;

    if Assigned(FProgress) and not FCloseAfterImport then
      while FProgress.ModalResult <> mrOk do
        Application.ProcessMessages;
    if FCloseAfterImport then
      Close;
  finally
    if Assigned(FProgress) then
    begin
      FProgress.Free;
      FProgress := nil;
    end;
  end;
end;

procedure TQImport2WizardF.TuneFormats;
begin
  pgImport.ActivePage := tsFormats;
  pgFieldOptions.ActivePage := tsFieldTuning;
  laStep_06.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                              {$IFDEF LINUX}QIW_Step{$ENDIF}, [2,3]);
  pgFormats.ActivePage := tshBaseFormats;
  TuneButtons;
end;

procedure TQImport2WizardF.TuneMap;
var
  i: integer;
begin
  case FImportType of
    aiXLS: begin
      impXLS.Map.Clear;
      for i := 0 to lvXLSFields.Items.Count - 1 do
        if TMapRow(lvXLSFields.Items[i].Data).AsString <> EmptyStr then
          impXLS.Map.Values[lvXLSFields.Items[i].Caption] :=
            TMapRow(lvXLSFields.Items[i].Data).AsString;
    end;
    aiDBF: begin
      impDBF.Map.Clear;
      for i := 0 to lstDBFMap.Items.Count - 1 do
        impDBF.Map.Values[lstDBFMap.Items[i].Caption] :=
          lstDBFMap.Items[i].SubItems[1];
    end;
    aiXML: begin
      impXML.Map.Clear;
      for i := 0 to lvXMLMap.Items.Count - 1 do
        impXML.Map.Values[lvXMLMap.Items[i].Caption] :=
          lvXMLMap.Items[i].SubItems[1];
    end;
    aiTXT: begin
      impASCII.Map.Clear;
      for i := 0 to lvTXTFields.Items.Count - 1 do
        if StrToIntDef(lvTXTFields.Items[i].SubItems[1], 0) > 0 then
          impASCII.Map.Values[lvTXTFields.Items[i].Caption] :=
            Format('%s;%s', [lvTXTFields.Items[i].SubItems[0],
                             lvTXTFields.Items[i].SubItems[1]]);
    end;
    aiCSV: begin
      impASCII.Map.Clear;
      for i := 0 to lvCSVFields.Items.Count - 1 do
        if StrToIntDef(lvCSVFields.Items[i].SubItems[0], 0) > 0 then
          impASCII.Map.Values[lvCSVFields.Items[i].Caption] :=
            IntToStr(StrToInt(lvCSVFields.Items[i].SubItems[0]));
    end;
  end;
end;

procedure TQImport2WizardF.SetTitle;
begin
  if FileName <> EmptyStr then
    Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ImportWizard){$ENDIF}
               {$IFDEF LINUX}QIW_ImportWizard{$ENDIF} + ' - ' +
      Format({$IFDEF WIN32}QImportLoadStr(QIW_ImportFrom){$ENDIF}
             {$IFDEF LINUX}QIW_ImportFrom{$ENDIF} + ' %s', [ExtractFileName(FileName)])
  else Caption := {$IFDEF WIN32}QImportLoadStr(QIW_ImportWizard){$ENDIF}
                  {$IFDEF LINUX}QIW_ImportWizard{$ENDIF};
end;

procedure TQImport2WizardF.bHelpClick(Sender: TObject);
begin
  if FileExists(ExtractFilePath(Application.ExeName) + QI_WIZARD_HELP) then begin
    HelpFile := ExtractFilePath(Application.ExeName) + QI_WIZARD_HELP;
    Application.HelpCommand(HELP_CONTENTS, 0);
  end;
end;

procedure TQImport2WizardF.SetEnabledDataFormatControls;
var
  FGenStep: integer;
begin
  // generator
  edtGeneratorValue.Enabled := (edtConstantValue.Text = EmptyStr) and
    (edtNullValue.Text = EmptyStr) and (edtDefaultValue.Text = EmptyStr) and
    (edtLeftQuote.Text = EmptyStr) and (edtRightQuote.Text = EmptyStr) and
    (TQuoteAction(cmbQuoteAction.ItemIndex) = qaNone) and
    (TQImportCharCase(cmbCharCase.ItemIndex) = iccNone) and
    (TQImportCharSet(cmbCharSet.ItemIndex) = icsNone);
  laGeneratorValue.Enabled := edtGeneratorValue.Enabled;
  edtGeneratorStep.Enabled := edtGeneratorValue.Enabled;
  laGeneratorStep.Enabled := edtGeneratorValue.Enabled;

  FGenStep := StrToIntDef(edtGeneratorStep.Text, 0);
  //constant
  edtConstantValue.Enabled := (FGenStep = 0) and
    (edtNullValue.Text = EmptyStr) and (edtDefaultValue.Text = EmptyStr);
  laConstantValue.Enabled := edtConstantValue.Enabled;
  // default
  edtNullValue.Enabled := (FGenStep = 0) and (edtConstantValue.Text = EmptyStr);
  laNullValue.Enabled := edtNullValue.Enabled;
  edtDefaultValue.Enabled := edtNullValue.Enabled;
  laDefaultValue.Enabled := edtNullValue.Enabled;
  // quotation
  edtLeftQuote.Enabled := FGenStep = 0;
  laLeftQuote.Enabled := edtLeftQuote.Enabled;
  edtRightQuote.Enabled := edtLeftQuote.Enabled;
  laRightQuote.Enabled := edtLeftQuote.Enabled;
  cmbQuoteAction.Enabled := edtLeftQuote.Enabled;
  laQuoteAction.Enabled := edtLeftQuote.Enabled;
  // string coversion
  cmbCharCase.Enabled := FGenStep = 0;
  laCharCase.Enabled := cmbCharCase.Enabled;
  cmbCharSet.Enabled := cmbCharCase.Enabled;
  laCharSet.Enabled := cmbCharCase.Enabled;
end;

procedure TQImport2WizardF.edtGeneratorValueChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).GeneratorValue :=
      StrToIntDef(edtGeneratorValue.Text, 0);
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.edtGeneratorStepChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).GeneratorStep :=
      StrToIntDef(edtGeneratorStep.Text, 0);
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.edtConstantValueChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).ConstantValue :=
      edtConstantValue.Text;
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.edtNullValueChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).NullValue :=
      edtNullValue.Text;
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.edtDefaultValueChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).DefaultValue :=
      edtDefaultValue.Text;
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.edtLeftQuoteChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).LeftQuote :=
      edtLeftQuote.Text;
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.edtRightQuoteChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).RightQuote :=
      edtRightQuote.Text;
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.cmbQuoteActionChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).QuoteAction :=
      TQuoteAction(cmbQuoteAction.ItemIndex);
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.cmbCharCaseChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).CharCase :=
      TQImportCharCase(cmbCharCase.ItemIndex);
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.cmbCharSetChange(Sender: TObject);
begin
  if Assigned(lstFormatFields.Selected) and not FLoadingFormatItem then begin
    TQImportFieldFormat(lstFormatFields.Selected.Data).CharSet :=
      TQImportCharSet(cmbCharSet.ItemIndex);
    SetEnabledDataFormatControls;
  end;
end;

procedure TQImport2WizardF.ApplyDataFormats(AImport: TQImport2);
var
  i, j: integer;
begin
  if lstFormatFields.Items.Count = 0 then Exit;
  for i := 0 to lstFormatFields.Items.Count - 1 do begin
    j := AImport.FieldFormats.IndexByName(lstFormatFields.Items[i].Caption);
    if j > -1 then
      AImport.FieldFormats[j].Assign(TQImportFieldFormat(lstFormatFields.Items[i].Data))
    else begin
      if not TQImportFieldFormat(lstFormatFields.Items[i].Data).IsDefaultValues then
        with AImport.FieldFormats.Add do
          Assign(TQImportFieldFormat(lstFormatFields.Items[i].Data));
    end;
  end;
end;

procedure TQImport2WizardF.lstFormatFieldsChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
begin
  if (csDestroying in ComponentState) or (Change <> ctState) then Exit;

  if Assigned(Item) and Assigned(Item.Data) and
     Item.Selected and (Item <> FFormatItem) then ShowFormatItem(Item);
  TuneButtons;
end;

procedure TQImport2WizardF.pgFormatsChange(Sender: TObject);
begin
  if pgFormats.ActivePage = tshDataFormats then begin
    ActiveControl := lstFormatFields;
    if (lstFormatFields.Items.Count > 0) and
       ((not Assigned(lstFormatFields.Selected)) or (not lstFormatFields.Selected.Focused)) then begin
      lstFormatFields.Items[0].Focused := true;
      lstFormatFields.Items[0].Selected := true;
      ShowFormatItem(lstFormatFields.Items[0]);
    end;
  end;
end;

procedure TQImport2WizardF.LoadTemplateFromFile(const AFileName: string);
var
  Template: TIniFile;
  i, j, k, l: integer;
  AStrings: TStrings;
  b: boolean;
  FF: TQImportFieldFormat;
  str: string;
  R: TQImportReplacement;
  textToFind, replaceWith: string;
  ignoreCase: Boolean;
begin
  if Wizard.ShowSaveLoadButtons then
  begin
    laTemplateFileName.Left := 168;
    laTemplateFileName.Width := 233;
  end
  else begin
    laTemplateFileNameTag.Left := 12;
    laTemplateFileName.Left := 12;
    laTemplateFileName.Width := 389;
  end;
  
  laTemplateFileNameTag.Visible :=
    FileExists(AFileName) and not Wizard.ShowSaveLoadButtons;

  if not FileExists(AFileName)
    then raise EQImportError.CreateFmt({$IFDEF WIN32}QImportLoadStr(QIE_FileNotExists){$ENDIF}
                                       {$IFDEF LINUX}QIE_FileNotExists{$ENDIF}, [AFileName]);

  laTemplateFileName.Caption := MinimizeName(AFileName,
    laTemplateFileName.Canvas, laTemplateFileName.Width);
  
  FTmpFileName := '';
  Template := TIniFile.Create(AFileName);
  try
    AStrings := TStringList.Create;
    try
      with Template do
      begin
        // ImportType
        Self.FileName := ReadString(QIW_FIRST_STEP, QIW_FILE_NAME, EmptyStr);
        if not Wizard.GoToLastPage then
          GoToLastPage := ReadBool(QIW_FIRST_STEP, QIW_GO_TO_LAST_PAGE, false);
        if not Wizard.AutoSaveTemplate then
          AutoSaveTemplate := ReadBool(QIW_FIRST_STEP, QIW_AUTO_SAVE_TEMPLATE, false);
        ImportType := TAllowedImport(ReadInteger(QIW_FIRST_STEP, QIW_IMPORT_TYPE, 0));
        case ImportType of
          // ExcelOptions
          aiXLS: begin
            ReadSection(QIW_XLS_MAP, AStrings);
            for i := 0 to AStrings.Count - 1 do
            begin
              j := -1;
              for k := 0 to lvXLSFields.Items.Count - 1 do
              begin
                if AnsiCompareText(lvXLSFields.Items[k].Caption, AStrings[i]) = 0 then
                begin
                  j := k;
                  Break;
                end;
              end;
              if j > -1 then
                TMapRow(lvXLSFields.Items[j].Data).AsString :=
                  ReadString(QIW_XLS_MAP, AStrings[i], EmptyStr);
            end;
            XLSSkipCols := ReadInteger(QIW_XLS_OPTIONS, QIW_XLS_SKIP_COLS, 0);
            XLSSkipRows := ReadInteger(QIW_XLS_OPTIONS, QIW_XLS_SKIP_ROWS, 0);
          end;
          aiTXT:
            FTmpFileName := AFileName;
          aiCSV: begin
            Comma := Str2Char(ReadString(QIW_CSV_OPTIONS, QIW_CSV_DELIMITER,
              Char2Str(GetListSeparator)), Comma);
            Quote := Str2Char(ReadString(QIW_CSV_OPTIONS, QIW_CSV_QUOTE, '"'),
              Quote);
            CSVSkipLines := ReadInteger(QIW_CSV_OPTIONS, QIW_CSV_SKIP_LINES, 0);

            ReadSection(QIW_CSV_MAP, AStrings);
            for i := 0 to AStrings.Count - 1 do
            begin
              j := -1;
              for k := 0 to lvCSVFields.Items.Count - 1 do
              begin
                if AnsiCompareText(lvCSVFields.Items[k].Caption, AStrings[i]) = 0 then
                begin
                  j := k;
                  Break;
                end;
              end;
              if j > -1 then
              begin
                str := ReadString(QIW_CSV_MAP, AStrings[i], EmptyStr);
                if StrToIntDef(str, 0) > 0 then
                  lvCSVFields.Items[j].SubItems[0] := str;
              end;
            end;
          end;
          aiDBF: begin
            DBFSkipDeleted := ReadBool(QIW_DBF_OPTIONS, QIW_DBF_SKIP_DELETED, true);
            lstDBFMap.Items.Clear;
            ReadSection(QIW_DBF_MAP, AStrings);
            for i := 0 to AStrings.Count - 1 do
            begin
              b := false;
              for j := 0 to QImportDestinationColCount(false,
                              ImportDestination, DataSet, DBGrid, ListView,
                              StringGrid) - 1 do
                b := b or (AnsiCompareText(AStrings[i],
                  QImportDestinationColName(false, ImportDestination, DataSet,
                    DBGrid, ListView, StringGrid, GridCaptionRow, j)) = 0);
              if not b then Continue;
              with lstDBFMap.Items.Add do
              begin
                Caption := AStrings[i];
                SubItems.Add('=');
                SubItems.Add(ReadString(QIW_DBF_MAP, AStrings[i], EmptyStr));
              end;
              for j := 0 to lstDBFDataSet.Items.Count - 1 do
              begin
                if AnsiCompareText(lstDBFDataSet.Items[j].Caption, AStrings[i]) = 0 then
                begin
                  lstDBFDataSet.Items[j].Delete;
                  Break;
                end;
              end;
            end;
            if lstDBFMap.Items.Count > 0 then
            begin
              lstDBFMap.Items[0].Focused := true;
              lstDBFMap.Items[0].Selected := true;
            end;
          end;
          aiXML: begin
            XMLWriteOnFly := ReadBool(QIW_XML_OPTIONS, QIW_XML_WRITE_ON_FLY, false);
            lvXMLMap.Items.Clear;
            ReadSection(QIW_XML_MAP, AStrings);
            for i := 0 to AStrings.Count - 1 do
            begin
              b := false;
              for j := 0 to QImportDestinationColCount(false,
                              ImportDestination, DataSet, DBGrid, ListView,
                              StringGrid) - 1 do
                b := b or (AnsiCompareText(AStrings[i],
                  QImportDestinationColName(false, ImportDestination, DataSet,
                    DBGrid, ListView, StringGrid, GridCaptionRow, j)) = 0);
              if not b then Continue;
              with lvXMLMap.Items.Add do
              begin
                Caption := AStrings[i];
                SubItems.Add('=');
                SubItems.Add(ReadString(QIW_XML_MAP, AStrings[i], EmptyStr));
              end;
              for j := 0 to lvXMLDataSet.Items.Count - 1 do
              begin
                if AnsiCompareText(lvXMLDataSet.Items[j].Caption, AStrings[i]) = 0 then
                begin
                  lvXMLDataSet.Items[j].Delete;
                  Break;
                end;
              end;
            end;
            if lvXMLMap.Items.Count > 0 then
            begin
              lvXMLMap.Items[0].Focused := true;
              lvXMLMap.Items[0].Selected := true;
            end;
          end;
        end;
        // Formats
        DecimalSeparator := Str2Char(ReadString(QIW_BASE_FORMATS,
          QIW_BF_DECIMAL_SEPARATOR, Char2Str(Wizard.Formats.DecimalSeparator)),
          Wizard.Formats.DecimalSeparator);
        ThousandSeparator := Str2Char(ReadString(QIW_BASE_FORMATS,
          QIW_BF_THOUSAND_SEPARATOR, Char2Str(Wizard.Formats.ThousandSeparator)),
          Wizard.Formats.ThousandSeparator);
        ShortDateFormat := ReadString(QIW_BASE_FORMATS, QIW_BF_SHORT_DATE_FORMAT,
          Wizard.Formats.ShortDateFormat);
        LongDateFormat := ReadString(QIW_BASE_FORMATS, QIW_BF_LONG_DATE_FORMAT,
          Wizard.Formats.LongDateFormat);
        DateSeparator := Str2Char(ReadString(QIW_BASE_FORMATS,
          QIW_BF_DATE_SEPARATOR, Char2Str(Wizard.Formats.DateSeparator)),
          Wizard.Formats.DateSeparator);
        ShortTimeFormat := ReadString(QIW_BASE_FORMATS, QIW_BF_SHORT_TIME_FORMAT,
          Wizard.Formats.ShortTimeFormat);
        LongTimeFormat := ReadString(QIW_BASE_FORMATS, QIW_BF_LONG_TIME_FORMAT,
          Wizard.Formats.LongTimeFormat);
        TimeSeparator := Str2Char(ReadString(QIW_BASE_FORMATS,
          QIW_BF_TIME_SEPARATOR, Char2Str(Wizard.Formats.TimeSeparator)),
          Wizard.Formats.TimeSeparator);
        ReadSection(QIW_BOOLEAN_TRUE, mmBooleanTrue.Lines);
        ReadSection(QIW_BOOLEAN_FALSE, mmBooleanFalse.Lines);
        ReadSection(QIW_NULL_VALUES, mmNullValues.Lines);
        // DataFormats
        ReadSections(AStrings);
        for i := 0 to AStrings.Count - 1 do
        begin
          if Pos(QIW_DATA_FORMATS, AStrings[i]) > 0 then
          begin
            for j := 0 to lstFormatFields.Items.Count - 1 do
              if AnsiCompareText(Copy(AStrings[i], Length(QIW_DATA_FORMATS) + 1,
                Length(AStrings[i])), lstFormatFields.Items[j].Caption) = 0 then
              begin
                FF := TQImportFieldFormat(lstFormatFields.Items[j].Data);
                FF.Replacements.Clear;
                FF.GeneratorValue := ReadInteger(AStrings[i],
                  QIW_DF_GENERATOR_VALUE, FF.GeneratorValue);
                FF.GeneratorStep := ReadInteger(AStrings[i],
                  QIW_DF_GENERATOR_STEP, FF.GeneratorStep);
                FF.ConstantValue := ReadString(AStrings[i],
                  QIW_DF_CONSTANT_VALUE, FF.ConstantValue);
                FF.NullValue := ReadString(AStrings[i], QIW_DF_NULL_VALUE,
                  FF.NullValue);
                FF.DefaultValue := ReadString(AStrings[i], QIW_DF_DEFAULT_VALUE,
                  FF.DefaultValue);
                FF.LeftQuote := ReadString(AStrings[i], QIW_DF_LEFT_QUOTE,
                  FF.LeftQuote);
                FF.RightQuote := ReadString(AStrings[i], QIW_DF_RIGHT_QUOTE,
                  FF.RightQuote);
                FF.QuoteAction := TQuoteAction(ReadInteger(AStrings[i],
                  QIW_DF_QUOTE_ACTION, Integer(FF.QuoteAction)));
                FF.CharCase := TQImportCharCase(ReadInteger(AStrings[i],
                  QIW_DF_CHAR_CASE, Integer(FF.CharCase)));
                FF.CharSet := TQImportCharSet(ReadInteger(AStrings[i],
                  QIW_DF_CHAR_SET, Integer(FF.CharSet)));
              end;
          end
          // Replacements
          else if Pos(QIW_REPLACEMENTS, AStrings[i]) = 1 then
          begin
            l := Length(AStrings[i]);
            while AStrings[i][l] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] do Dec(l);
            str := Copy(AStrings[i], Length(QIW_REPLACEMENTS) + 1,
                   l - Length(QIW_REPLACEMENTS) - 1);

            for j := 0 to lstFormatFields.Items.Count - 1 do
              if AnsiCompareText(str, lstFormatFields.Items[j].Caption) = 0 then
              begin
                FF := TQImportFieldFormat(lstFormatFields.Items[j].Data);
                textToFind := ReadString(AStrings[i], QIW_RP_TEXT_TO_FIND, EmptyStr);
                replaceWith := ReadString(AStrings[i], QIW_RP_REPLACE_WITH, EmptyStr);
                ignoreCase := ReadBool(AStrings[i], QIW_RP_IGNORE_CASE, false);
                if not FF.Replacements.ItemExists(textToFind, replaceWith, ignoreCase) then
                begin
                  R := FF.Replacements.Add;
                  R.TextToFind := textToFind;
                  R.ReplaceWith := replaceWith;
                  R.IgnoreCase := ignoreCase;
                end;  
              end;
              ShowFormatItem(lstFormatFields.ItemFocused);
          end;
        end;
        // LastStep
        if not Wizard.CommitAfterDone then
          CommitAfterDone := ReadBool(QIW_LAST_STEP, QIW_COMMIT_AFTER_DONE,
            Wizard.CommitAfterDone);
        CommitRecCount := ReadInteger(QIW_LAST_STEP, QIW_COMMIT_REC_COUNT,
          Wizard.CommitRecCount);
        ImportRecCount := ReadInteger(QIW_LAST_STEP, QIW_IMPORT_REC_COUNT,
          Wizard.ImportRecCount);
        if not Wizard.CloseAfterImport then
          CloseAfterImport := ReadBool(QIW_LAST_STEP, QIW_CLOSE_AFTER_IMPORT,
            Wizard.CloseAfterImport);
        EnableErrorLog := ReadBool(QIW_LAST_STEP, QIW_ENABLE_ERROR_LOG,
          Wizard.ErrorLog);
        ErrorLogFileName := ReadString(QIW_LAST_STEP, QIW_ERROR_LOG_FILE_NAME,
          Wizard.ErrorLogFileName);
        if not Wizard.RewriteErrorLogFile then
          RewriteErrorLogFile := ReadBool(QIW_LAST_STEP, QIW_REWRITE_ERROR_LOG_FILE,
            Wizard.RewriteErrorLogFile);
        if not Wizard.ShowErrorLog then
          ShowErrorLog := ReadBool(QIW_LAST_STEP, QIW_SHOW_ERROR_LOG, true);

        ImportMode := TQImportMode(ReadInteger(QIW_LAST_STEP, QIW_IMPORT_MODE,
          Integer(Wizard.ImportMode)));
        AddType := TQImportAddType(ReadInteger(QIW_LAST_STEP, QIW_ADD_TYPE,
          Integer(Wizard.AddType)));
        AStrings.Clear;
        ReadSection(QIW_KEY_COLUMNS, AStrings);
        FillKeyColumns(AStrings);
      end;
    finally
      AStrings.Free;
    end;
  finally
    Template.Free
  end;

  if Wizard.GoToLastPage then
  begin
    if (ImportType = aiTXT) and not TXTReady then
      TXTTune;
    if (((ImportType = aiXLS) and XLSReady) or
     ((ImportType = aiDBF) and DBFReady) or
     ((ImportType = aiXML) and XMLReady) or
     ((ImportType = aiTXT) and TXTReady) or
     ((ImportType = aiCSV) and CSVReady)) then
    Step := 3;
  end;
end;

procedure TQImport2WizardF.SaveTemplateToFile(const AFileName: string);
var
  Template: TIniFile;
  i, j: integer;
  str: string;
  ff: TQImportFieldFormat;
begin
  if Trim(AFileName) = EmptyStr then Exit;
  Template := TIniFile.Create(AFileName);
  try
    with Template do begin
      ClearIniFile(Template);
      WriteInteger(QIW_FIRST_STEP, QIW_IMPORT_TYPE, Integer(ImportType));
      WriteString(QIW_FIRST_STEP, QIW_FILE_NAME, Self.FileName);
      WriteBool(QIW_FIRST_STEP, QIW_GO_TO_LAST_PAGE, GoToLastPage);
      WriteBool(QIW_FIRST_STEP, QIW_AUTO_SAVE_TEMPLATE, AutoSaveTemplate);
      case ImportType of
        aiXLS: begin
          for i := 0 to lvXLSFields.Items.Count - 1 do
            if TMapRow(lvXLSFields.Items[i].Data).AsString <> EmptyStr
              then WriteString(QIW_XLS_MAP, lvXLSFields.Items[i].Caption,
                TMapRow(lvXLSFields.Items[i].Data).AsString);
          WriteInteger(QIW_XLS_OPTIONS, QIW_XLS_SKIP_COLS, XLSSkipCols);
          WriteInteger(QIW_XLS_OPTIONS, QIW_XLS_SKIP_ROWS, XLSSkipRows);
        end;
        aiTXT: begin
          for i := 0 to lvTXTFields.Items.Count - 1 do
            if StrToIntDef(lvTXTFields.Items[i].SubItems[1], 0) > 0 then
              WriteString(QIW_TXT_MAP, lvTXTFields.Items[i].Caption,
                Format('%s;%s', [lvTXTFields.Items[i].SubItems[0],
                                 lvTXTFields.Items[i].SubItems[1]]));
          WriteInteger(QIW_TXT_OPTIONS, QIW_TXT_SKIP_LINES,
            TXTSkipLines);
        end;
        aiCSV: begin
          for i := 0 to lvCSVFields.Items.Count - 1 do
            if StrToIntDef(lvCSVFields.Items[i].SubItems[0], 0) > 0 then
              WriteString(QIW_CSV_MAP, lvCSVFields.Items[i].Caption,
                lvCSVFields.Items[i].SubItems[0]);
          WriteInteger(QIW_CSV_OPTIONS, QIW_CSV_SKIP_LINES, CSVSkipLines);
          WriteString(QIW_CSV_OPTIONS, QIW_CSV_DELIMITER, Char2Str(Comma));
          WriteString(QIW_CSV_OPTIONS, QIW_CSV_QUOTE, Char2Str(Quote));
        end;
        aiDBF: begin
          WriteBool(QIW_DBF_OPTIONS, QIW_DBF_SKIP_DELETED, DBFSkipDeleted);
          for i := 0 to lstDBFMap.Items.Count - 1 do
            WriteString(QIW_DBF_MAP, lstDBFMap.Items[i].Caption,
              lstDBFMap.Items[i].SubItems[1]);
        end;
        aiXML: begin
          WriteBool(QIW_XML_OPTIONS, QIW_XML_WRITE_ON_FLY, XMLWriteOnFly);
          for i := 0 to lvXMLMap.Items.Count - 1 do
            WriteString(QIW_XML_MAP, lvXMLMap.Items[i].Caption,
              lvXMLMap.Items[i].SubItems[1]);
        end;
      end;
      // Formats
      WriteString(QIW_BASE_FORMATS, QIW_BF_DECIMAL_SEPARATOR,
        Char2Str(Self.DecimalSeparator));
      WriteString(QIW_BASE_FORMATS, QIW_BF_THOUSAND_SEPARATOR,
        Char2Str(Self.ThousandSeparator));
      WriteString(QIW_BASE_FORMATS, QIW_BF_SHORT_DATE_FORMAT,
        Self.ShortDateFormat);
      WriteString(QIW_BASE_FORMATS, QIW_BF_LONG_DATE_FORMAT,
        Self.LongDateFormat);
      WriteString(QIW_BASE_FORMATS, QIW_BF_DATE_SEPARATOR,
        Char2Str(Self.DateSeparator));
      WriteString(QIW_BASE_FORMATS, QIW_BF_SHORT_TIME_FORMAT,
        Self.ShortTimeFormat);
      WriteString(QIW_BASE_FORMATS, QIW_BF_LONG_TIME_FORMAT,
        Self.LongTimeFormat);
      WriteString(QIW_BASE_FORMATS, QIW_BF_TIME_SEPARATOR,
        Char2Str(Self.TimeSeparator));
      for i := 0 to mmBooleanTrue.Lines.Count - 1 do
        WriteString(QIW_BOOLEAN_TRUE, mmBooleanTrue.Lines[i], EmptyStr);
      for i := 0 to mmBooleanFalse.Lines.Count - 1 do
        WriteString(QIW_BOOLEAN_FALSE, mmBooleanFalse.Lines[i], EmptyStr);
      for i := 0 to mmNullValues.Lines.Count - 1 do
        WriteString(QIW_NULL_VALUES, mmNullValues.Lines[i], EmptyStr);
      for i := 0 to lstFormatFields.Items.Count - 1 do begin
        ff := TQImportFieldFormat(lstFormatFields.Items[i].Data);
        str := QIW_DATA_FORMATS + AnsiUpperCase(ff.FieldName);
        if ff.GeneratorStep <> 0 then begin
          WriteInteger(str, QIW_DF_GENERATOR_VALUE, ff.GeneratorValue);
          WriteInteger(str, QIW_DF_GENERATOR_STEP, ff.GeneratorStep);
          Continue;
        end;
        if ff.ConstantValue <> EmptyStr then
          WriteString(str, QIW_DF_CONSTANT_VALUE, ff.ConstantValue);
        if (ff.ConstantValue = EmptyStr) and
           (ff.NullValue <> EmptyStr) and (ff.DefaultValue <> EmptyStr) then begin
          WriteString(str, QIW_DF_NULL_VALUE, ff.NullValue);
          WriteString(str, QIW_DF_DEFAULT_VALUE, ff.DefaultValue);
        end;
        if ff.LeftQuote <> EmptyStr then
          WriteString(str, QIW_DF_LEFT_QUOTE, ff.LeftQuote);
        if ff.RightQuote <> EmptyStr then
          WriteString(str, QIW_DF_RIGHT_QUOTE, ff.RightQuote);
        if ff.QuoteAction <> qaNone then
          WriteInteger(str, QIW_DF_QUOTE_ACTION, Integer(ff.QuoteAction));
        if ff.CharCase <> iccNone then
          WriteInteger(str, QIW_DF_CHAR_CASE, Integer(ff.CharCase));
        if ff.CharSet <> icsNone then
          WriteInteger(str, QIW_DF_CHAR_SET, Integer(ff.CharSet));
        // Replacements
        str := QIW_REPLACEMENTS + AnsiUpperCase(ff.FieldName);
        for j := 0 to ff.Replacements.Count - 1 do begin
          WriteString(Format('%s_%d', [str, j]), QIW_RP_TEXT_TO_FIND,
            ff.Replacements[j].TextToFind);
          WriteString(Format('%s_%d', [str, j]), QIW_RP_REPLACE_WITH,
            ff.Replacements[j].ReplaceWith);
          WriteBool(Format('%s_%d', [str, j]), QIW_RP_IGNORE_CASE,
            ff.Replacements[j].IgnoreCase);
        end;
      end;
      // Last Step
      WriteBool(QIW_LAST_STEP, QIW_COMMIT_AFTER_DONE, CommitAfterDone);
      WriteInteger(QIW_LAST_STEP, QIW_COMMIT_REC_COUNT, CommitRecCount);
      WriteInteger(QIW_LAST_STEP, QIW_IMPORT_REC_COUNT, ImportRecCount);
      WriteBool(QIW_LAST_STEP, QIW_CLOSE_AFTER_IMPORT, CloseAfterImport);
      WriteBool(QIW_LAST_STEP, QIW_ENABLE_ERROR_LOG, EnableErrorLog);
      WriteString(QIW_LAST_STEP, QIW_ERROR_LOG_FILE_NAME, ErrorLogFileName);
      WriteBool(QIW_LAST_STEP, QIW_REWRITE_ERROR_LOG_FILE, RewriteErrorLogFile);
      WriteBool(QIW_LAST_STEP, QIW_SHOW_ERROR_LOG, ShowErrorLog);

      WriteInteger(QIW_LAST_STEP, QIW_IMPORT_MODE, Integer(ImportMode));
      WriteInteger(QIW_LAST_STEP, QIW_ADD_TYPE, Integer(AddType));
      EraseSection(QIW_KEY_COLUMNS);
      for i := 0 to lvSelectedColumns.Items.Count -1 do
        WriteString(QIW_KEY_COLUMNS, lvSelectedColumns.Items[i].Caption, EmptyStr);
    end;
  finally
    Template.Free;
  end;
end;

procedure TQImport2WizardF.btnLoadTemplateClick(Sender: TObject);
begin
  if odTemplate.Execute then begin
    if Assigned(Wizard.OnLoadTemplate) then
      Wizard.OnLoadTemplate(Wizard, odTemplate.FileName);
    LoadTemplateFromFile(odTemplate.FileName);
  end;
end;

procedure TQImport2WizardF.btnSaveTemplateClick(Sender: TObject);
begin
  if sdTemplate.Execute then
    SaveTemplateToFile(sdTemplate.FileName);
end;

// XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS
// XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS
// XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS XLS
procedure TQImport2WizardF.XLSFillFieldList;
var
  i: integer;
begin
  if not (aiXLS in Wizard.AllowedImports) then Exit;
  if not QImportDestinationAssigned(false, ImportDestination, DataSet, DBGrid,
           ListView, StringGrid) then Exit;
  XLSClearFieldList;
  for i := 0 to QImportDestinationColCount(false, ImportDestination, DataSet,
                  DBGrid, ListView, StringGrid) - 1 do
    with lvXLSFields.Items.Add do begin
      Caption := QImportDestinationColName(false, ImportDestination, DataSet,
        DBGrid, Self.ListView, StringGrid, GridCaptionRow, i);
      ImageIndex := 0;
      Data := TMapRow.Create(nil);
    end;
end;

procedure TQImport2WizardF.XLSClearFieldList;
var
  i: integer;
begin
  for i := lvXLSFields.Items.Count - 1 downto 0 do begin
    if Assigned(lvXLSFields.Items[i].Data) then
      TMapRow(lvXLSFields.Items[i].Data).Free;
    lvXLSFields.Items.Delete(i);
  end;
end;

procedure TQImport2WizardF.XLSClearDataSheets;
var
  i: integer;
begin
  for i := pcXLSFile.PageCount - 1 downto 0 do
    pcXLSFile.Pages[i].Free;
end;

procedure TQImport2WizardF.XLSFillGrid;
var
  TabSheet: TTabSheet;
  StringGrid: TStringGrid;
  k, i, j, n: integer;
  Cell: TbiffCell;
  V: Variant;
  F: TForm;
  Start, Finish: TDateTime;
  W: integer;
  ExprLen: word;
  Expr: PByteArray;
begin
  XLSClearDataSheets;

  if not FileExists(FFileName) then Exit;

  FXLSFile.FileName := FFileName;
  Start := Now;
  F := ShowLoading(Self, FFileName);
  try
    Application.ProcessMessages;
    FXLSFile.Clear;
    FXLSFile.Load;

    for k := 0 to FXLSFile.Workbook.WorkSheets.Count - 1 do begin
      TabSheet := TTabSheet.Create(pcXLSFile);
      TabSheet.PageControl := pcXLSFile;
      TabSheet.Caption := FXLSFile.Workbook.WorkSheets[k].Name;

      StringGrid := TStringGrid.Create(TabSheet);
      StringGrid.Parent := TabSheet;
      StringGrid.Align := alClient;
      StringGrid.ColCount := 257;
      n := 65536;
      if (Wizard.ExcelViewerRows > 0) and (Wizard.ExcelViewerRows <= 65536) then
        n := Wizard.ExcelViewerRows;
      StringGrid.RowCount := n + 1;
      StringGrid.FixedCols := 1;
      StringGrid.FixedRows := 1;
      StringGrid.DefaultColWidth := 64;
      StringGrid.DefaultRowHeight := 16;
      StringGrid.ColWidths[0] := 30;
      StringGrid.Options := StringGrid.Options - [goRangeSelect];
      StringGrid.OnClick := XLSGridClick;
      StringGrid.OnDrawCell := XLSDrawCell;
      StringGrid.OnMouseDown := XLSMouseDown;
      StringGrid.OnSelectCell := XLSSelectCell;
      StringGrid.OnExit := XLSGridExit;
      StringGrid.OnKeyDown := XLSGridKeyDown;
      StringGrid.Tag := 1000;

      GridFillFixedCells(StringGrid);

      for i := 0 to FXLSFile.Workbook.WorkSheets[k].Rows.Count - 1 do
        for j := 0 to FXLSFile.Workbook.WorkSheets[k].Rows[i].Count - 1 do begin
          Cell := FXLSFile.Workbook.WorkSheets[k].Rows[i][j];
          if (Cell.Col < StringGrid.ColCount - 1) and
             (Cell.Row < StringGrid.RowCount - 1) then begin
            case Cell.CellType of
              bctString  :
                StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] := Cell.AsString;
              bctBoolean :
                if Cell.AsBoolean
                  then StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] := 'true'
                  else StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] := 'false';
              bctNumeric :
                StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] :=
                  FloatToStr(Cell.AsFloat);
              bctDateTime:
                if Cell.AsDateTime = 0 then begin
                  StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] :=
                    FormatDateTime(FShortTimeFormat, Cell.AsDateTime)
                end
                else begin
                  if Cell.IsDateOnly then
                    StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] :=
                      FormatDateTime(FShortDateFormat, Cell.AsDateTime)
                  else if Cell.IsTimeOnly then
                    StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] :=
                      FormatDateTime(FShortTimeFormat, Cell.AsDateTime)
                  else StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] :=
                    FormatDateTime(FShortDateFormat + ' ' + FShortTimeFormat,
                      Cell.AsDateTime);
                end;
              bctUnknown :
                if Cell.IsFormula then begin
                  ExprLen := GetWord(Cell.Data, 20);
                  if ExprLen > 0 then begin
                    GetMem(Expr, ExprLen);
                    try
                      Move(Cell.Data[22], Expr^, ExprLen);
                      V := CalculateFormula(Cell, Expr, ExprLen);
                    finally
                      FreeMem(Expr);
                    end;
                  end
                  else V := NULL;
                  StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] := VarToStr(V);
                end
                else
                  StringGrid.Cells[Cell.Col + 1, Cell.Row + 1] :=
                    VarToStr(Cell.AsVariant);
            end;
            W := StringGrid.Canvas.TextWidth(StringGrid.Cells[Cell.Col + 1, Cell.Row + 1]);
            if W + 10 > StringGrid.ColWidths[Cell.Col + 1] then
              if W + 10 < Wizard.ExcelMaxColWidth
                then StringGrid.ColWidths[Cell.Col + 1] := W + 10
                else StringGrid.ColWidths[Cell.Col + 1] := Wizard.ExcelMaxColWidth;
          end;
        end;
    end;
  finally
    Finish := Now;
    while (Finish - Start) < EncodeTime(0, 0, 0, 500) do
      Finish := Now;

    if Assigned(F) then
      F.Free;
  end;

  FNeedLoadFile := false;
end;

procedure TQImport2WizardF.XLSTune;
begin
  ShowTip(tsExcelOptions, 6, 21, 39, 557, {$IFDEF WIN32}QImportLoadStr(QIW_XLS_Tip){$ENDIF}
                                          {$IFDEF LINUX}QIW_XLS_Tip{$ENDIF});

  pgImport.ActivePage := tsExcelOptions;
  laStep_04.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                              {$IFDEF LINUX}QIW_Step{$ENDIF}, [1,3]);

  edXLSSkipCols.OnChange(nil);
  edXLSSkipRows.OnChange(nil);

  if lvXLSFields.Items.Count > 0 then
    if not Assigned(lvXLSFields.ItemFocused) then begin
      lvXLSFields.Items[0].Focused := true;
      lvXLSFields.Items[0].Selected := true;
      lvXLSFields.SetFocus;
    end;

  if FNeedLoadFile then XLSFillGrid;
  TuneButtons;
end;

procedure TQImport2WizardF.SetXLSSkipCols(const Value: integer);
begin
  if FXLSSkipCols <> Value then begin
    FXLSSkipCols := Value;
    edXLSSkipCols.Text := IntToStr(Value);
    XLSRepaintCurrentGrid;
    TuneButtons;
  end;
end;

procedure TQImport2WizardF.SetXLSSkipRows(const Value: integer);
begin
  if FXLSSkipRows <> Value then begin
    FXLSSkipRows := Value;
    edXLSSkipRows.Text := IntToStr(Value);
    XLSRepaintCurrentGrid;
    TuneButtons;
  end;
end;

function TQImport2WizardF.XLSReady: boolean;
var
  i: integer;
begin
  Result := false;
  for i := 0 to lvXLSFields.Items.Count - 1 do
    if TMapRow(lvXLSFields.Items[i].Data).Count > 0 then begin
      Result := true;
      Break;
    end;
end;

procedure TQImport2WizardF.XLSDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  i: integer;
begin
  FXLSDefinedRanges.Clear;
  if lvXLSFields.Focused then begin
    if Assigned(lvXLSFields.ItemFocused) and
       Assigned(lvXLSFields.ItemFocused.Data) then
      for i := 0 to TMapRow(lvXLSFields.ItemFocused.Data).Count - 1 do
        FXLSDefinedRanges.Add(TMapRow(lvXLSFields.ItemFocused.Data)[i]);
  end
  else begin
    if Assigned(lvXLSFields.ItemFocused) and
       Assigned(lvXLSFields.ItemFocused.Data) and
       Assigned(lvXLSRanges.ItemFocused) then
      FXLSDefinedRanges.Add(TMapRow(lvXLSFields.ItemFocused.Data)[lvXLSRanges.ItemFocused.Index]);
  end;

  if Sender is TStringGrid then
    GridDrawCell(Sender as TStringGrid, pcXLSFile.ActivePage.Caption,
      pcXLSFile.ActivePage.PageIndex + 1, ACol, ARow, Rect, State,
      FXLSDefinedRanges, XLSSkipCols, XLSSkipRows, FXLSIsEditingGrid,
      FXLSGridSelection);
end;

procedure TQImport2WizardF.XLSMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

  procedure AddColRowToSelection(IsCol, IsCtrl: boolean; Number: integer);
  var
    str, str1: string;
    N: integer;
  begin
    if IsCol
      then str := Format('[%s]%s-%s;', [pcXLSFile.ActivePage.Caption, Col2Letter(Number), COLFINISH])
      else str := Format('[%s]%s-%s;', [pcXLSFile.ActivePage.Caption, Row2Number(Number), ROWFINISH]);

      N := FXLSGridSelection.IndexOfRange(str);
      if N > -1 then FXLSGridSelection.Delete(N);

      if (not IsCtrl) or (N = -1) then begin
        str1 := FXLSGridSelection.AsString;
        str1 := str1 + str;
        FXLSGridSelection.AsString := str1;
      end;
  end;

var
  Grid: TStringGrid;
  ACol, ARow, SCol, SRow, N, i: integer;
  IsCtrl, IsShift: boolean;

  procedure ChangeCurrentCell(Col, Row: integer);
  var
    Event: TSelectCellEvent;
  begin
    Event := Grid.OnSelectCell;
    Grid.OnSelectCell := nil;
    Grid.Col := Col;
    Grid.Row := Row;
    Grid.OnSelectCell := Event;
  end;

begin
  if not (Sender is TStringGrid) then Exit;
  Grid := Sender as TStringGrid;

  IsShift := GetKeyState(VK_SHIFT) < 0;
  IsCtrl := GetKeyState(VK_CONTROL) < 0;

  if not (IsShift or IsCtrl) then begin
    Grid.Repaint;
    Exit;
  end;

  Grid.MouseToCell(X, Y, ACol, ARow);

  if not ((ACol = 0) xor (ARow = 0)) then begin
    Grid.Repaint;
    Exit;
  end;

  if not FXLSIsEditingGrid then
    XLSStartEditing;

  if IsCtrl then begin
    if ACol = 0
      then N := ARow
      else N := ACol;

    AddColRowToSelection(ARow = 0, true, N);

    if ACol = 0
      then ChangeCurrentCell(Grid.Col, ARow)
      else ChangeCurrentCell(ACol, Grid.Row);
  end
  else if IsShift then begin
    SCol := Grid.Col;
    SRow := Grid.Row;

    if ACol = 0 then begin
      if SRow <= ARow then
        for i := SRow to ARow do
          AddColRowToSelection(false, false, i)
      else
        for i := SRow downto ARow do
          AddColRowToSelection(false, false, i);
      ChangeCurrentCell(Grid.Col, ARow);
    end
    else begin
      if SCol <= ACol then
        for i := SCol to ACol do
          AddColRowToSelection(true, false, i)
      else
        for i := SCol downto ACol do
          AddColRowToSelection(true, false, i);
      ChangeCurrentCell(ACol, Grid.Row);
    end;
  end;

  XLSFillSelection;
  Grid.Repaint;
end;

procedure TQImport2WizardF.XLSSelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
var
  Grid: TStringGrid;
  SCol, SRow, i: integer;
  Str: string;
  IsShift, IsCtrl, Cut: boolean;
begin
  if not (Sender is TStringGrid) then Exit;
  Grid := Sender as TStringGrid;
//  try
    IsShift := GetKeyState(VK_SHIFT) < 0;
    IsCtrl := GetKeyState(VK_CONTROL) < 0;

    if not (IsShift or IsCtrl) then begin
      XLSFinishEditing;
      Exit;
    end;

    SCol := Grid.Col;
    SRow := Grid.Row;

    if IsShift and not ((SCol = ACol) or (SRow = ARow)) then begin
      XLSFinishEditing;
      Exit;
    end;

    if not FXLSIsEditingGrid then
      XLSStartEditing;

    Cut := false;
    if (SCol = ACol) and (SRow = ARow) then begin
    end
    else begin
      if IsShift then begin
        if FXLSGridSelection.Count > 0 then begin

          if SCol <> ACol then begin
            if FXLSGridSelection[FXLSGridSelection.Count - 1].RangeType = rtRow then begin
              if SCol > ACol then begin
                for i := SCol downto ACol + 1 do
                  if CellInRange(FXLSGridSelection[FXLSGridSelection.Count - 1],
                       pcXLSFile.ActivePage.Caption,
                       pcXLSFile.ActivePage.PageIndex + 1, i, ARow) then begin
                    Cut := true;
                    FXLSGridSelection[FXLSGridSelection.Count - 1].Col2 :=
                      FXLSGridSelection[FXLSGridSelection.Count - 1].Col2 - 1;
                  end;
              end
              else begin
                for i := SCol to ACol - 1 do
                  if (FXLSGridSelection[FXLSGridSelection.Count - 1].RangeType = rtRow) and
                     CellInRange(FXLSGridSelection[FXLSGridSelection.Count - 1],
                       pcXLSFile.ActivePage.Caption,
                       pcXLSFile.ActivePage.PageIndex + 1, i, ARow) then begin
                    Cut := true;
                    FXLSGridSelection[FXLSGridSelection.Count - 1].Col2 :=
                      FXLSGridSelection[FXLSGridSelection.Count - 1].Col2 + 1;
                  end;
              end;
            end
          end
          else if SRow <> ARow then begin
            if (FXLSGridSelection[FXLSGridSelection.Count - 1].RangeType = rtCol) then begin
              if SRow > ARow then begin
                for i := SRow downto ARow + 1 do
                  if CellInRange(FXLSGridSelection[FXLSGridSelection.Count - 1],
                       pcXLSFile.ActivePage.Caption,
                       pcXLSFile.ActivePage.PageIndex + 1, ACol, i) then begin
                    Cut := true;
                    FXLSGridSelection[FXLSGridSelection.Count - 1].Row2 :=
                      FXLSGridSelection[FXLSGridSelection.Count - 1].Row2 - 1;
                  end;
              end
              else begin
                for i := SRow to ARow - 1 do
                  if CellInRange(FXLSGridSelection[FXLSGridSelection.Count - 1],
                       pcXLSFile.ActivePage.Caption,
                       pcXLSFile.ActivePage.PageIndex + 1, ACol, i) then begin
                    Cut := true;
                    FXLSGridSelection[FXLSGridSelection.Count - 1].Row2 :=
                      FXLSGridSelection[FXLSGridSelection.Count - 1].Row2 + 1;
                  end;
              end;
            end;
          end;

          if (FXLSGridSelection[FXLSGridSelection.Count - 1].Col2 = SCol) and
             (FXLSGridSelection[FXLSGridSelection.Count - 1].Row2 = SRow) then begin
            if FXLSGridSelection[FXLSGridSelection.Count - 1].Col2 = ACol then begin
              if ARow > SRow
                then SRow := SRow + 1
                else SRow := SRow - 1;
            end
            else if FXLSGridSelection[FXLSGridSelection.Count - 1].Row2 = ARow then begin
              if ACol > SCol
                then SCol := SCol + 1
                else SCol := SCol - 1;
            end;
          end;

        end;
        if not Cut then begin
          str := FXLSGridSelection.AsString;
          if SCol = ACol then begin
            if SRow > ARow then begin
              for i := SRow downto ARow do
                if not CellInRow(FXLSGridSelection, EmptyStr, pcXLSFile.ActivePage.PageIndex + 1, ACol, i) then
                  str := str + Format('[%s]%s%d;', [pcXLSFile.ActivePage.Caption, Col2Letter(ACol), i]);
            end
            else begin
              for i := SRow to ARow do
                if not CellInRow(FXLSGridSelection, EmptyStr, pcXLSFile.ActivePage.PageIndex + 1, ACol, i) then
                  str := str + Format('[%s]%s%d;', [pcXLSFile.ActivePage.Caption, Col2Letter(ACol), i]);
            end
          end
          else if SRow = ARow then begin
            if SCol > ACol then begin
              for i := SCol downto ACol do
                if not CellInRow(FXLSGridSelection, EmptyStr, pcXLSFile.ActivePage.PageIndex + 1, i, ARow) then
                  str := str + Format('[%s]%s%d;', [pcXLSFile.ActivePage.Caption, Col2Letter(i), ARow]);
            end
            else begin
              for i := SCol to ACol do
                if not CellInRow(FXLSGridSelection, EmptyStr, pcXLSFile.ActivePage.PageIndex + 1, i, ARow) then
                  str := str + Format('[%s]%s%d;', [pcXLSFile.ActivePage.Caption, Col2Letter(i), ARow]);
            end
          end;
          FXLSGridSelection.AsString := str;
        end;
        XLSFillSelection;
      end
      else if IsCtrl then begin
        if not CellInRow(FXLSGridSelection, EmptyStr,
             pcXLSFile.ActivePage.PageIndex + 1, ACol, ARow) then begin
          str := FXLSGridSelection.AsString;
          str := str + Format('[%s]%s%d;', [pcXLSFile.ActivePage.Caption, Col2Letter(ACol), ARow]);
          FXLSGridSelection.AsString := str;
        end
        else begin
          RemoveCellFromRow(FXLSGridSelection, EmptyStr,
            pcXLSFile.ActivePage.PageIndex + 1, ACol, ARow);
        end;
        XLSFillSelection;
      end;
    end;
{  finally
    Grid.Repaint;
  end;}
end;

procedure TQImport2WizardF.XLSGridExit(Sender: TObject);
begin
  XLSFinishEditing;
end;

procedure TQImport2WizardF.XLSGridKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Shift = [] then
    case Key of
      VK_RETURN: XLSApplyEditing;
      VK_ESCAPE: XLSFinishEditing;
    end;
end;

procedure TQImport2WizardF.XLSGridClick(Sender: TObject);
begin
  if Sender is TStringGrid then
    (Sender as TStringGrid).Repaint;
end;

procedure TQImport2WizardF.XLSStartEditing;
begin
  FXLSIsEditingGrid := true;
  lvXLSRanges.Visible := false;
  lvXLSSelection.Visible := true;
  tbXLSRanges.Visible := false;
end;

procedure TQImport2WizardF.XLSFinishEditing;
begin
  FXLSIsEditingGrid := false;
  FXLSGridSelection.Clear;
  XLSRepaintCurrentGrid;

  lvXLSSelection.Visible:= false;

  lvXLSRanges.Visible := true;
  tbXLSRanges.Visible := true;;
end;

procedure TQImport2WizardF.XLSApplyEditing;
var
  i: integer;
begin
  if FXLSGridSelection.Count = 0 then Exit;

  XLSDeleteSelectedRanges;

  for i := 0 to FXLSGridSelection.Count - 1 do begin
    FXLSGridSelection[i].MapRow := TMapRow(lvXLSFields.ItemFocused.Data);
    TMapRow(lvXLSFields.ItemFocused.Data).Add(FXLSGridSelection[i]);
    with lvXLSRanges.Items.Add do begin
      Caption := FXLSGridSelection[i].AsString;
      Data := FXLSGridSelection[i];
      ImageIndex := 3;
    end;
  end;
  if (lvXLSRanges.Items.Count > 0) and
     not Assigned(lvXLSRanges.ItemFocused) then begin
    lvXLSRanges.Items[0].Focused := true;
    lvXLSRanges.Items[0].Selected := true;
  end;

  XLSFinishEditing;
end;

procedure TQImport2WizardF.XLSDeleteSelectedRanges;
var
  List: TList;
  i: integer;
begin
  if lvXLSRanges.SelCount = 0 then Exit;

  lvXLSRanges.OnChange := nil;
  try
    List := TList.Create;
    try
      for i := 0 to lvXLSRanges.Items.Count - 1 do
        if lvXLSRanges.Items[i].Selected then
          List.Add(Pointer(i));
      for i := List.Count - 1 downto 0 do begin
        TMapRow(lvXLSFields.ItemFocused.Data).Delete(Integer(List[i]));
        lvXLSRanges.Items[Integer(List[i])].Delete;
        List.Delete(i);
      end;

      if (lvXLSRanges.Items.Count > 0) and Assigned(lvXLSRanges.ItemFocused) and
         not lvXLSRanges.ItemFocused.Selected then
        lvXLSRanges.ItemFocused.Selected := true;

    finally
      List.Free;
    end;
    TuneButtons;
  finally
    lvXLSRanges.OnChange := lvXLSRangesChange;
  end;
end;

function TQImport2WizardF.XLSGetCurrentGrid: TStringGrid;
var
  i: integer;
begin
  Result := nil;
  if not Assigned(pcXLSFile.ActivePage) then Exit;
  for i := 0 to pcXLSFile.ActivePage.ComponentCount - 1 do
    if (pcXLSFile.ActivePage.Components[i] is TStringGrid) and
       ((pcXLSFile.ActivePage.Components[i] as TStringGrid).Tag  = 1000) then begin
      Result := pcXLSFile.ActivePage.Components[i] as TStringGrid;
      Break;
    end;
end;

procedure TQImport2WizardF.XLSRepaintCurrentGrid;
var
  Grid: TStringGrid;
begin
  Grid := XLSGetCurrentGrid;
  if Assigned(Grid) then Grid.Repaint;
end;

procedure TQImport2WizardF.XLSFillSelection;
var
  i: integer;
begin
//  lvXLSSelection.Items.BeginUpdate;
  try
    lvXLSSelection.Items.Clear;
    FXLSGridSelection.Optimize;
    for i := 0 to FXLSGridSelection.Count - 1 do
      with lvXLSSelection.Items.Add do begin
        Caption := FXLSGridSelection[i].AsString;
        ImageIndex := 3;
      end;
    if lvXLSSelection.Items.Count > 0 then begin
      lvXLSSelection.Items[0].Focused := true;
      lvXLSSelection.Items[0].Selected := true;
    end
  finally
  //  lvXLSSelection.Items.EndUpdate;
  end;
end;

procedure TQImport2WizardF.btnXLSAutoFillColsClick(Sender: TObject);
var
  i, j: integer;
  MapRow: TMapRow;
  MR: TMapRange;
begin
  j := pcXLSFile.ActivePage.TabIndex;

  for i := 0 to lvXLSFields.Items.Count - 1 do begin
    MapRow := TMapRow(lvXLSFields.Items[i].Data);
    MapRow.Clear;
    if i <= FXLSFile.Workbook.WorkSheets[j].ColCount - 1 then begin
      MR := TMapRange.Create(MapRow);
      MR.Col1 := FXLSFile.Workbook.WorkSheets[j].Cols[i].ColNumber + 1;
      MR.Col2 := MR.Col1;
      MR.Row1 := 0;
      MR.Row2 := 0;
      MR.SheetIDType := sitName;
      MR.SheetName := FXLSFile.Workbook.WorkSheets[j].Name;
      MR.SheetNumber := 0;
      MR.Direction := rdDown;
      MapRow.Add(MR);
    end;
  end;
  if Assigned(lvXLSFields.ItemFocused) then
    lvXLSFieldsChange(lvXLSFields, lvXLSFields.ItemFocused, ctState);
  TuneButtons;
end;

procedure TQImport2WizardF.btnXLSAutoFillRowsClick(Sender: TObject);
var
  i, j: integer;
  MapRow: TMapRow;
  MR: TMapRange;
begin
  j := pcXLSFile.ActivePage.TabIndex;

  for i := 0 to lvXLSFields.Items.Count - 1 do begin
    MapRow := TMapRow(lvXLSFields.Items[i].Data);
    MapRow.Clear;
    if i <= FXLSFile.Workbook.WorkSheets[j].RowCount - 1 then begin
      MR := TMapRange.Create(MapRow);
      MR.Row1 := FXLSFile.Workbook.WorkSheets[j].Rows[i].RowNumber + 1;
      MR.Row2 := MR.Row1;
      MR.Col1 := 0;
      MR.Col2 := 0;
      MR.SheetIDType := sitName;
      MR.SheetName := FXLSFile.Workbook.WorkSheets[j].Name;
      MR.SheetNumber := 0;
      MR.Direction := rdDown;
      MapRow.Add(MR);
    end;
  end;

  if Assigned(lvXLSFields.ItemFocused) then
    lvXLSFieldsChange(lvXLSFields, lvXLSFields.ItemFocused, ctState);
  TuneButtons;
end;

procedure TQImport2WizardF.lvXLSFieldsChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
var
  i: integer;
  Row: TMapRow;
begin
  if not Assigned(Item) or not Assigned(Item.Data) then Exit;
//  lvXLSRanges.Items.BeginUpdate;
  try
    lvXLSRanges.Items.Clear;
    Row := TMapRow(Item.Data);
    for i := 0 to Row.Count - 1 do
      with lvXLSRanges.Items.Add do begin
        Caption := Row[i].AsString;
        ImageIndex := 3;
        Data := Row[i];
      end;
    if lvXLSRanges.Items.Count > 0 then begin
      lvXLSRanges.Items[0].Focused := true;
      lvXLSRanges.Items[0].Selected := true;
    end
    else lvXLSRangesChange(lvXLSRanges, nil, ctState);

    XLSRepaintCurrentGrid;
  finally
  //  lvXLSRanges.Items.EndUpdate;
  end;
  TuneButtons;
end;

{procedure TQImportWizardF.lvXLSFieldsSelectItem(Sender: TObject;
  Item: TListItem; Selected: Boolean);
var
  i: integer;
  Row: TMapRow;
begin
  if not Assigned(Item) or not Assigned(Item.Data) then Exit;
//  lvXLSRanges.Items.BeginUpdate;
  try
    lvXLSRanges.Items.Clear;
    Row := TMapRow(Item.Data);
    for i := 0 to Row.Count - 1 do
      with lvXLSRanges.Items.Add do begin
        Caption := Row[i].AsString;
        ImageIndex := 3;
        Data := Row[i];
      end;
    if lvXLSRanges.Items.Count > 0 then begin
      lvXLSRanges.Items[0].Focused := true;
      lvXLSRanges.Items[0].Selected := true;
    end
    else lvXLSRangesSelectItem(lvXLSRanges, nil, false);

    XLSRepaintCurrentGrid;
  finally
  //  lvXLSRanges.Items.EndUpdate;
  end;
  TuneButtons;
end;}

procedure TQImport2WizardF.tbtXLSAddRangeClick(Sender: TObject);
var
  Range: TMapRange;
  MapRow: TMapRow;
  i: integer;
  Item: TListItem;
begin
  MapRow := TMapRow(lvXLSFields.ItemFocused.Data);
  Range := TMapRange.Create(MapRow);
  Range.Col1 := 1;
  Range.Row1 := 0;
  Range.Col2 := 1;
  Range.Row2 := 0;
  Range.Direction := rdDown;
  Range.SheetIDType := sitName;
  Range.SheetName := pcXLSFile.ActivePage.Caption;
  Range.SheetNumber := pcXLSFile.ActivePage.PageIndex + 1;
  Range.Update;

  if EditRange(Range, FXLSFile) then begin
    MapRow.Add(Range);
    lvXLSRanges.Items.BeginUpdate;
    try
      Item := lvXLSRanges.Items.Add;
      with Item do begin
        Caption := Range.AsString;
        ImageIndex := 3;
        Data := Range;
      end;
      for i := 0 to lvXLSRanges.Items.Count - 1 do begin
        lvXLSRanges.Items[i].Focused := lvXLSRanges.Items[i] = Item;
        lvXLSRanges.Items[i].Selected := lvXLSRanges.Items[i] = Item;
      end;
    finally
      lvXLSRanges.Items.EndUpdate;
    end;
  end
  else Range.Free;
  TuneButtons;
end;

procedure TQImport2WizardF.tbtXLSEditRangeClick(Sender: TObject);
begin
  if not Assigned(lvXLSFields.ItemFocused) and
     not Assigned(lvXLSRanges.ItemFocused) then Exit;

  if EditRange(TMapRange(lvXLSRanges.ItemFocused.Data), FXLSFile) then
    lvXLSRanges.ItemFocused.Caption := TMapRange(lvXLSRanges.ItemFocused.Data).AsString;
  XLSRepaintCurrentGrid;
  TuneButtons;
end;

procedure TQImport2WizardF.lvXLSRangesChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
begin
  XLSRepaintCurrentGrid;
  TuneButtons;
end;

procedure TQImport2WizardF.tbtXLSMoveRangeUpClick(Sender: TObject);
var
  Index, i: integer;
begin
  Index := lvXLSRanges.ItemFocused.Index;
  TMapRow(lvXLSFields.ItemFocused.Data).Exchange(Index, Index - 1);
  lvXLSRanges.Items.BeginUpdate;
  try
    lvXLSRanges.Items[Index].Data := TMapRow(lvXLSFields.ItemFocused.Data)[Index];
    lvXLSRanges.Items[Index].Caption := TMapRange(lvXLSRanges.Items[Index].Data).AsString;
    lvXLSRanges.Items[Index - 1].Data := TMapRow(lvXLSFields.ItemFocused.Data)[Index - 1];
    lvXLSRanges.Items[Index - 1].Caption := TMapRange(lvXLSRanges.Items[Index - 1].Data).AsString;
    for i := 0 to lvXLSRanges.Items.Count - 1 do begin
      lvXLSRanges.Items[i].Focused := lvXLSRanges.Items[i] = lvXLSRanges.Items[Index - 1];
      lvXLSRanges.Items[i].Selected := lvXLSRanges.Items[i] = lvXLSRanges.Items[Index - 1];
    end;
  finally
    lvXLSRanges.Items.EndUpdate;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.tbtXLSMoveRangeDownClick(Sender: TObject);
var
  Index, i: integer;
begin
  Index := lvXLSRanges.ItemFocused.Index;
  TMapRow(lvXLSFields.ItemFocused.Data).Exchange(Index, Index + 1);
  lvXLSRanges.Items.BeginUpdate;
  try
    lvXLSRanges.Items[Index].Data := TMapRow(lvXLSFields.ItemFocused.Data)[Index];
    lvXLSRanges.Items[Index].Caption := TMapRange(lvXLSRanges.Items[Index].Data).AsString;
    lvXLSRanges.Items[Index + 1].Data := TMapRow(lvXLSFields.ItemFocused.Data)[Index + 1];
    lvXLSRanges.Items[Index + 1].Caption := TMapRange(lvXLSRanges.Items[Index + 1].Data).AsString;
    for i := 0 to lvXLSRanges.Items.Count - 1 do begin
      lvXLSRanges.Items[i].Focused := lvXLSRanges.Items[i] = lvXLSRanges.Items[Index + 1];
      lvXLSRanges.Items[i].Selected := lvXLSRanges.Items[i] = lvXLSRanges.Items[Index + 1];
    end;
  finally
    lvXLSRanges.Items.EndUpdate;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.tbtXLSDelRangeClick(Sender: TObject);
begin
  XLSDeleteSelectedRanges;
  XLSRepaintCurrentGrid;
end;

procedure TQImport2WizardF.tbtXLSClearFieldRangesClick(Sender: TObject);
begin
  if not (Assigned(lvXLSFields.ItemFocused) and
          Assigned(lvXLSFields.ItemFocused.Data)) then Exit;
  TMapRow(lvXLSFields.ItemFocused.Data).Clear;
  lvXLSFieldsChange(lvXLSFields, lvXLSFields.ItemFocused, ctState);
end;

procedure TQImport2WizardF.edXLSSkipColsChange(Sender: TObject);
begin
  XLSSkipCols := StrToIntDef(edXLSSkipCols.Text, 0);
end;

procedure TQImport2WizardF.edXLSSkipRowsChange(Sender: TObject);
begin
  XLSSkipRows := StrToIntDef(edXLSSkipRows.Text, 0);
end;

procedure TQImport2WizardF.lvXLSRangesDblClick(Sender: TObject);
begin
  if tbtXLSEditRange.Enabled then
    tbtXLSEditRange.Click;
end;

procedure TQImport2WizardF.tbtXLSClearAllRangesClick(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to lvXLSFields.Items.Count - 1 do
    TMapRow(lvXLSFields.Items[i].Data).Clear;
  lvXLSFieldsChange(lvXLSFields, lvXLSFields.ItemFocused, ctState);
  TuneButtons;
end;

// Formats Formats Formats Formats Formats Formats Formats Formats Formats
// Formats Formats Formats Formats Formats Formats Formats Formats Formats
// Formats Formats Formats Formats Formats Formats Formats Formats Formats

procedure TQImport2WizardF.SetDecimalSeparator(const Value: char);
begin
  if FDecimalSeparator <> Value then begin
    FDecimalSeparator := Value;
    edtDecimalSeparator.Text := Char2Str(FDecimalSeparator);
  end;
end;

procedure TQImport2WizardF.SetThousandSeparator(const Value: char);
begin
  if FThousandSeparator <> Value then begin
    FThousandSeparator := Value;
    edtThousandSeparator.Text := Char2Str(FThousandSeparator);
  end;
end;

procedure TQImport2WizardF.SetShortDateFormat(const Value: string);
begin
  if FShortDateFormat <> Value then begin
    FShortDateFormat := Value;
    edtShortDateFormat.Text := FShortDateFormat;
  end;
end;

procedure TQImport2WizardF.SetLongDateFormat(const Value: string);
begin
  if FLongDateFormat <> Value then begin
    FLongDateFormat := Value;
    edtLongDateFormat.Text := FLongDateFormat;
  end;
end;

procedure TQImport2WizardF.SetDateSeparator(const Value: char);
begin
  if FDateSeparator <> Value then begin
    FDateSeparator := Value;
    edtDateSeparator.Text := Char2Str(FDateSeparator);
  end;
end;

procedure TQImport2WizardF.SetShortTimeFormat(const Value: string);
begin
  if FShortTimeFormat <> Value then begin
    FShortTimeFormat := Value;
    edtShortTimeFormat.Text := FShortTimeFormat;
  end;
end;

procedure TQImport2WizardF.SetLongTimeFormat(const Value: string);
begin
  if FLongTimeFormat <> Value then begin
    FLongTimeFormat := Value;
    edtLongTimeFormat.Text := FlongTimeFormat;
  end;
end;

procedure TQImport2WizardF.SetTimeSeparator(const Value: char);
begin
  if FTimeSeparator <> Value then begin
    FTimeSeparator := Value;
    edtTimeSeparator.Text := Char2Str(FTimeSeparator);
  end;
end;

procedure TQImport2WizardF.edtDecimalSeparatorExit(Sender: TObject);
begin
  DecimalSeparator := Str2Char(edtDecimalSeparator.Text, DecimalSeparator);
end;

procedure TQImport2WizardF.edtThousandSeparatorExit(Sender: TObject);
begin
  ThousandSeparator := Str2Char(edtThousandSeparator.Text, ThousandSeparator);
end;

procedure TQImport2WizardF.edtShortDateFormatChange(Sender: TObject);
begin
  ShortDateFormat := edtShortDateFormat.Text;
end;

procedure TQImport2WizardF.edtLongDateFormatChange(Sender: TObject);
begin
  LongDateFormat := edtLongDateFormat.Text;
end;

procedure TQImport2WizardF.edtDateSeparatorExit(Sender: TObject);
begin
  DateSeparator := Str2Char(edtDateSeparator.Text, DateSeparator);
end;

procedure TQImport2WizardF.edtShortTimeFormatChange(Sender: TObject);
begin
  ShortTimeFormat := edtShortTimeFormat.Text;
end;

procedure TQImport2WizardF.edtLongTimeFormatChange(Sender: TObject);
begin
  LongTimeFormat := edtLongTimeFormat.Text;
end;

procedure TQImport2WizardF.edtTimeSeparatorExit(Sender: TObject);
begin
  TimeSeparator := Str2Char(edtTimeSeparator.Text, TimeSeparator);
end;

procedure TQImport2WizardF.FormatsFillList;
var
  i, j: integer;
begin
  FormatsClearList;
  for i := 0 to QImportDestinationColCount(false,
                  ImportDestination, DataSet, DBGrid, ListView,
                  StringGrid) - 1 do begin
    with lstFormatFields.Items.Add do begin
      Caption := QImportDestinationColName(false, ImportDestination, DataSet,
                 DBGrid, Self.ListView, StringGrid, GridCaptionRow, i);
      Data := TQImportFieldFormat.Create(nil);
      ImageIndex := 0;
      with TQImportFieldFormat(Data) do begin
        FieldName := QImportDestinationColName(false, ImportDestination,
                     DataSet, DBGrid, Self.ListView, StringGrid, GridCaptionRow, i);
        j := FieldFormats.IndexByName(FieldName);
        if j = -1 then Continue;
        GeneratorValue := FieldFormats[j].GeneratorValue;
        GeneratorStep := FieldFormats[j].GeneratorStep;
        ConstantValue := FieldFormats[j].ConstantValue;
        NullValue := FieldFormats[j].NullValue;
        DefaultValue := FieldFormats[j].DefaultValue;
        QuoteAction := FieldFormats[j].QuoteAction;
        LeftQuote := FieldFormats[j].LeftQuote;
        RightQuote := FieldFormats[j].RightQuote;
        CharCase := FieldFormats[j].CharCase;
        CharSet := FieldFormats[j].CharSet;
      end;
    end;
  end;
  if lstFormatFields.Items.Count > 0 then begin
    lstFormatFields.Items[0].Focused := true;
    lstFormatFields.Items[0].Selected := true;
    ShowFormatItem(lstFormatFields.Items[0])
  end;
end;

procedure TQImport2WizardF.FormatsClearList;
var
  i: integer;
begin
  for i := lstFormatFields.Items.Count - 1 downto 0 do begin
    if Assigned(lstFormatFields.Items[i].Data) then
      TQImportFieldFormat(lstFormatFields.Items[i].Data).Free;
    lstFormatFields.Items.Delete(i);
  end;
end;

procedure TQImport2WizardF.ShowFormatItem(Item: TListItem);
var
  FieldFormat: TQImportFieldFormat;
  i: integer;
begin
  if not Assigned(Item) then Exit;
  FLoadingFormatItem := true;
  try
    FieldFormat := TQImportFieldFormat(Item.Data);
    edtGeneratorValue.Text := IntToStr(FieldFormat.GeneratorValue);
    edtGeneratorStep.Text := IntToStr(FieldFormat.GeneratorStep);
    edtConstantValue.Text := FieldFormat.ConstantValue;
    edtNullValue.Text := FieldFormat.NullValue;
    edtDefaultValue.Text := FieldFormat.DefaultValue;
    edtLeftQuote.Text := FieldFormat.LeftQuote;
    edtRightQuote.Text := FieldFormat.RightQuote;
    cmbQuoteAction.ItemIndex := Integer(FieldFormat.QuoteAction);
    cmbCharCase.ItemIndex := Integer(FieldFormat.CharCase);
    cmbCharSet.ItemIndex := Integer(FieldFormat.CharSet);

    lvReplacements.Items.BeginUpdate;
    try
      lvReplacements.Items.Clear;
      for i := 0 to FieldFormat.Replacements.Count - 1 do
        with lvReplacements.Items.Add do begin
          Caption := FieldFormat.Replacements[i].TextToFind;
          SubItems.Add(FieldFormat.Replacements[i].ReplaceWith);
          if FieldFormat.Replacements[i].IgnoreCase
            then SubItems.Add({$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase_Yes){$ENDIF}
                              {$IFDEF LINUX}QIWDF_IgnoreCase_Yes{$ENDIF})
            else SubItems.Add({$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase_No){$ENDIF}
                              {$IFDEF LINUX}QIWDF_IgnoreCase_No{$ENDIF});
          ImageIndex := 3;
          Data := FieldFormat.Replacements[i];
        end;
      if lvReplacements.Items.Count > 0 then begin
        lvReplacements.Items[0].Focused := true;
        lvReplacements.Items[0].Selected := true;
      end;
    finally
      lvReplacements.Items.EndUpdate;
    end;

    SetEnabledDataFormatControls;
  finally
    FLoadingFormatItem := false;
  end;
end;

// Last Step Last Step Last Step Last Step Last Step Last Step Last Step Last Step
// Last Step Last Step Last Step Last Step Last Step Last Step Last Step Last Step
// Last Step Last Step Last Step Last Step Last Step Last Step Last Step Last Step

procedure TQImport2WizardF.SetCommitAfterDone(const Value: boolean);
begin
  if FCommitAfterDone <> Value then begin
    FCommitAfterDone := Value;
    chCommitAfterDone.Checked := FCommitAfterDone;
  end;
end;

procedure TQImport2WizardF.SetCommitRecCount(const Value: integer);
begin
  if FCommitRecCount <> Value then begin
    FCommitRecCount := Value;
    edtCommitRecCount.Text := IntToStr(FCommitRecCount);
  end;
end;

procedure TQImport2WizardF.chCommitAfterDoneClick(Sender: TObject);
begin
  CommitAfterDone := chCommitAfterDone.Checked;
end;

procedure TQImport2WizardF.edtCommitRecCountChange(Sender: TObject);
begin
  try
    CommitRecCount := StrToInt(edtCommitRecCount.Text);
  except
  end;
end;

procedure TQImport2WizardF.SetImportRecCount(const Value: integer);
begin
  if FImportRecCount <> Value then
    FImportRecCount := Value;
  edtImportRecCount.Text := IntToStr(FImportRecCount);
  chImportAllRecords.Checked := FImportRecCount = 0;
end;

procedure TQImport2WizardF.chImportAllRecordsClick(Sender: TObject);
begin
  edtImportRecCount.Enabled := not chImportAllRecords.Checked;
  laImportRecCount_01.Enabled := not chImportAllRecords.Checked;
  laImportRecCount_02.Enabled := not chImportAllRecords.Checked;
end;

procedure TQImport2WizardF.edtImportRecCountChange(Sender: TObject);
begin
  try
    ImportRecCount := StrToInt(edtImportRecCount.Text);
  except
    edtImportRecCount.Text := IntToStr(ImportRecCount);
  end;
end;

procedure TQImport2WizardF.SetCloseAfterImport(const Value: boolean);
begin
  if FCloseAfterImport <> Value then
  begin
    FCloseAfterImport := Value;
    chCloseAfterImport.Checked := FCloseAfterImport;
  end;
end;

procedure TQImport2WizardF.chCloseAfterImportClick(Sender: TObject);
begin
  CloseAfterImport := chCloseAfterImport.Checked;
end;

procedure TQImport2WizardF.SetEnableErrorLog(const Value: boolean);
begin
  if FEnableErrorLog <> Value then begin
    FEnableErrorLog := Value;
    chEnableErrorLog.Checked := FEnableErrorLog;
  end;
end;

procedure TQImport2WizardF.SetErrorLogFileName(const Value: string);
begin
  if FErrorLogFileName <> Value then begin
    FErrorLogFileName := Value;
    edErrorLogFileName.Text := FErrorLogFileName;
  end;
end;

procedure TQImport2WizardF.SetRewriteErrorLogFile(const Value: boolean);
begin
  if FRewriteErrorLogFile <> Value then begin
    FRewriteErrorLogFile := Value;
    chRewriteErrorLogFile.Checked := FRewriteErrorLogFile;
  end;
end;

procedure TQImport2WizardF.SetShowErrorLog(const Value: boolean);
begin
  if FShowErrorLog <> Value then begin
    if Value and not EnableErrorLog then Exit;
    FShowErrorLog := Value;
    chShowErrorLog.Checked := FShowErrorLog;
  end;
end;

procedure TQImport2WizardF.SetImportMode(const Value: TQImportMode);
begin
  if FImportMode <> Value then begin
    FImportMode := Value;
    rgImportMode.ItemIndex := Integer(FImportMode);
  end;
end;

procedure TQImport2WizardF.SetAddType(const Value: TQImportAddType);
begin
  if FAddType <> Value then begin
    FAddType := Value;
    rgAddType.ItemIndex := Integer(FAddType);
  end;
end;

procedure TQImport2WizardF.chEnableErrorLogClick(Sender: TObject);
begin
  EnableErrorLog := chEnableErrorLog.Checked;
  chShowErrorLog.Enabled := FEnableErrorLog;
  laErrorLogFileName.Enabled := FEnableErrorLog;
  edErrorLogFileName.Enabled := FEnableErrorLog;
  chRewriteErrorLogFile.Enabled := FEnableErrorLog;
  bErrorLogFileName.Enabled := FEnableErrorLog;
end;

procedure TQImport2WizardF.edErrorLogFileNameChange(Sender: TObject);
begin
  ErrorLogFileName := edErrorLogFileName.Text;
end;

procedure TQImport2WizardF.bErrorLogFileNameClick(Sender: TObject);
var
  Path: string;
begin
  if edErrorLogFileName.Text <> EmptyStr then begin
    Path := ExtractFilePath(edErrorLogFileName.Text);
    if Path = EmptyStr then GetDir(0, Path);
    sdErrorLog.InitialDir := Path;
  end;
  if sdErrorLog.Execute then edErrorLogFileName.Text := sdErrorLog.FileName;
end;

procedure TQImport2WizardF.chRewriteErrorLogFileClick(Sender: TObject);
begin
  RewriteErrorLogFile := chRewriteErrorLogFile.Checked;
end;

procedure TQImport2WizardF.chShowErrorLogClick(Sender: TObject);
begin
  ShowErrorLog := chShowErrorLog.Checked;
end;

procedure TQImport2WizardF.rgImportModeClick(Sender: TObject);
begin
  ImportMode := TQImportMode(rgImportMode.ItemIndex);
end;

procedure TQImport2WizardF.rgAddTypeClick(Sender: TObject);
begin
  AddType := TQImportAddType(rgAddType.ItemIndex);
end;

procedure TQImport2WizardF.bAllToRightClick(Sender: TObject);
begin
  MoveToSelected(lvAvailableColumns, lvSelectedColumns, true, -1);
end;

procedure TQImport2WizardF.bOneToRirghtClick(Sender: TObject);
begin
  MoveToSelected(lvAvailableColumns, lvSelectedColumns, false, -1);
end;

procedure TQImport2WizardF.bOneToLeftClick(Sender: TObject);
begin
  MoveToSelected(lvSelectedColumns, lvAvailableColumns, false, -1);
end;

procedure TQImport2WizardF.bAllToLeftClick(Sender: TObject);
begin
  MoveToSelected(lvSelectedColumns, lvAvailableColumns, true, -1);
end;

procedure TQImport2WizardF.lvAvailableColumnsDblClick(Sender: TObject);
begin
  MoveToSelected(lvAvailableColumns, lvSelectedColumns, false, -1);
end;

procedure TQImport2WizardF.lvSelectedColumnsDblClick(Sender: TObject);
begin
  MoveToSelected(lvSelectedColumns, lvAvailableColumns, false, -1);
end;

procedure TQImport2WizardF.KeyColumnsDragOver(Sender,
  Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
  Accept := Source is TListView;
end;

procedure TQImport2WizardF.KeyColumnsDragDrop(Sender,
  Source: TObject; X, Y: Integer);
var
  ListItem: TListItem;
  Index, i: integer;
  str: string;
begin
  if Source <> Sender then begin
    ListItem := (Sender as TListView).GetItemAt(X, Y);
    if Assigned(ListItem)
      then Index := ListItem.Index + 1
      else Index := -1;
    if Source = lvAvailableColumns
      then MoveToSelected(lvAvailableColumns, lvSelectedColumns, false, Index);
    if Source = lvSelectedColumns
      then MoveToSelected(lvSelectedColumns, lvAvailableColumns, false, Index);
  end
  else begin
    with (Sender as TListView) do begin
      ListItem := GetItemAt(X, Y);
      if Assigned(ListItem) and Assigned(Selected) then begin
        Items.BeginUpdate;
        try
          str := Selected.Caption;
          Items.Delete(Selected.Index);
          ListItem := Items.Insert(ListItem.Index + 1);
          ListItem.Caption := str;
          for i := 0 to Items.Count - 1 do begin
            Items[i].Focused := Items[i] = ListItem;
            Items[i].Selected := Items[i] = ListItem;
          end;
        finally
          Items.EndUpdate;
        end;
      end;
    end;
  end;
end;

// TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT
// TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT
// TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT TXT

procedure TQImport2WizardF.TXTTune;
var
  i, j, k, p, s: integer;
  strings: TStrings;
begin
  if FNeedLoadFile then
  begin
    vwTXT.LineCount := Wizard.TextViewerRows;
    vwTXT.LoadFromFile(FileName);
    FNeedLoadFile := false;

    if (FTmpFileName <> '') and FileExists(FileName) then
    begin
      with TIniFile.Create(FTmpFileName) do
      try
        strings := TStringList.Create;
        try
          ReadSection(QIW_TXT_MAP, strings);
          for i := 0 to strings.Count - 1 do
          begin
            j := -1;
            for k := 0 to lvTXTFields.Items.Count - 1 do
            begin
              if AnsiCompareText(lvTXTFields.Items[k].Caption, strings[i]) = 0 then
              begin
                j := k;
                Break;
              end;
            end;
            if j > -1 then
            begin
              TXTExtractPosSize(ReadString(QIW_TXT_MAP, strings[i],
                EmptyStr), p, s);
              vwTXT.AddArrow(p);
              vwTXT.AddArrow(p + s);
              lvTXTFields.Items[j].SubItems[0] := IntToStr(p);
              lvTXTFields.Items[j].SubItems[1] := IntToStr(s);
            end;
          end;
          TXTSkipLines := ReadInteger(QIW_TXT_OPTIONS, QIW_TXT_SKIP_LINES, 0);
        finally
          strings.Free;
        end;
      finally
        Free;
      end;
    end;
  end;

  ShowTip(tsTXTOptions, 6, 21, 39, 557, {$IFDEF WIN32}QImportLoadStr(QIW_TXT_Tip){$ENDIF}
                                        {$IFDEF LINUX}QIW_TXT_Tip{$ENDIF});

  pgImport.ActivePage := tsTXTOptions;
  laTXTStep_02.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                                 {$IFDEF LINUX}QIW_Step{$ENDIF}, [1, 3]);


  if (lvTXTFields.Items.Count > 0) and
     not Assigned(lvTXTFields.Selected) then
  begin
    lvTXTFields.Items[0].Focused := true;
    lvTXTFields.Items[0].Selected := true;
  end;

  lvTXTFieldsChange(lvTXTFields, lvTXTFields.Selected, ctState);
  TuneButtons;
end;

function TQImport2WizardF.TXTReady: boolean;
var
  i: integer;
begin
  Result := false;
  for i := 0 to lvTXTFields.Items.Count - 1 do begin
    Result := StrToIntDef(lvTXTFields.Items[i].SubItems[1], -1) > -1;
    if Result then Break;
  end;
end;

procedure TQImport2WizardF.TXTFillCombo;
var
  i: integer;
begin
  if not (aiTXT in Wizard.AllowedImports) then Exit;
  if not QImportDestinationAssigned(false, ImportDestination, DataSet, DBGrid,
           ListView, StringGrid) then Exit;
  TXTClearCombo;
  for i := 0 to QImportDestinationColCount(false, ImportDestination, DataSet,
                  DBGrid, ListView, StringGrid) - 1 do
    with lvTXTFields.Items.Add do begin
      Caption := QImportDestinationColName(false, ImportDestination, DataSet,
        DBGrid, Self.ListView, StringGrid, GridCaptionRow, i);
      SubItems.Add(EmptyStr);
      SubItems.Add(EmptyStr);
    end;
end;

procedure TQImport2WizardF.TXTClearCombo;
begin
  lvTXTFields.Items.Clear;
end;

procedure TQImport2WizardF.TXTExtractPosSize(const S: string; var Position,
  Size: integer);
var
  i: integer;
  b: boolean;
begin
  i := Pos(';', S);
  b := S[Length(S)] = ';';
  if i = 0 then Exit;
  try
    Position := StrToInt(Copy(S, 1, i - 1));
    Size := StrToInt(Copy(S, i + 1, Length(S) - i - Integer(b)))
  except
  end;
end;

procedure TQImport2WizardF.SetTXTSkipLines(const Value: integer);
begin
  if FTXTSkipLines <> Value then begin
    FTXTSkipLines := Value;
    edtTXTSkipLines.Text := IntToStr(FTXTSkipLines);
  end;
end;

procedure TQImport2WizardF.edtTXTSkipLinesChange(Sender: TObject);
begin
  TXTSkipLines := StrToIntDef(edtTXTSkipLines.Text, 0);
end;

procedure TQImport2WizardF.lvTXTFieldsChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
var
  P, S: integer;
begin
  if not Assigned(Item) then Exit;
  if Item.SubItems.Count < 2 then Exit;
  P := StrToIntDef(Item.SubItems[0], -1);
  S := StrToIntDef(Item.SubItems[1], -1);
  vwTXT.SetSelection(P, S);
  vwTXT.Repaint;
  TuneButtons;
end;

procedure TQImport2WizardF.tbtTXTClearClick(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to lvTXTFields.Items.Count - 1 do begin
    lvTXTFields.Items[i].SubItems[0] := EmptyStr;
    lvTXTFields.Items[i].SubItems[1] := EmptyStr;
  end;
  lvTXTFieldsChange(lvTXTFields, lvTXTFields.ItemFocused, ctState);
end;

procedure TQImport2WizardF.TXTViewerChangeSelection(Sender: TObject);
var
  P, S: integer;
begin
  if not Assigned(lvTXTFields.ItemFocused) then Exit;
  vwTXT.GetSelection(P, S);
  if (P > -1) and (S > -1) then begin
    lvTXTFields.ItemFocused.SubItems[0] := IntToStr(P);
    lvTXTFields.ItemFocused.SubItems[1] := IntToStr(S);
  end
  else begin
    lvTXTFields.ItemFocused.SubItems[0] := EmptyStr;
    lvTXTFields.ItemFocused.SubItems[1] := EmptyStr;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.TXTViewerDeleteArrow(Sender: TObject;
  Position: integer);
var
  i, p, s: integer;
begin
  for i := 0 to lvTXTFields.Items.Count - 1 do begin
    p := StrToIntDef(lvTXTFields.Items[i].SubItems[0], -1);
    s := StrToIntDef(lvTXTFields.Items[i].SubItems[1], -1);
    if (p > -1) and (s > -1) and
       ((p = Position) or (p + s = Position)) then begin
      lvTXTFields.Items[i].SubItems[0] := EmptyStr;
      lvTXTFields.Items[i].SubItems[1] := EmptyStr;
    end;
  end;
end;

procedure TQImport2WizardF.TXTViewerMoveArrow(Sender: TObject;
  OldPos, NewPos: integer);
var
  i, p, s: integer;
begin
  for i := 0 to lvTXTFields.Items.Count - 1 do begin
    p := StrToIntDef(lvTXTFields.Items[i].SubItems[0], -1);
    s := StrToIntDef(lvTXTFields.Items[i].SubItems[1], -1);
    if (p > -1) and (s > -1) then begin
      if p = OldPos then
        lvTXTFields.Items[i].SubItems[0] := IntToStr(NewPos)
      else if p + s = OldPos then
        lvTXTFields.Items[i].SubItems[1] := IntToStr(NewPos - p);
    end;
  end;
end;

procedure TQImport2WizardF.TXTViewerIntersectArrows(Sender: TObject;
  Position: integer);
var
  i, p, s: integer;
begin
  for i := 0 to lvTXTFields.Items.Count - 1 do begin
    p := StrToIntDef(lvTXTFields.Items[i].SubItems[0], -1);
    s := StrToIntDef(lvTXTFields.Items[i].SubItems[1], -1);
    if (p > -1) and (s > -1) and
       ((p = Position) or (p + s = Position)) then begin
      lvTXTFields.Items[i].SubItems[0] := EmptyStr;
      lvTXTFields.Items[i].SubItems[1] := EmptyStr;
    end;
  end;
end;

// CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV
// CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV
// CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV CSV

procedure TQImport2WizardF.CSVFillCombo;
var
  i: integer;
begin
  if not (aiCSV in Wizard.AllowedImports) then Exit;
  if not QImportDestinationAssigned(false, ImportDestination, DataSet, DBGrid,
           ListView, StringGrid) then Exit;
  CSVClearCombo;
  for i := 0 to QImportDestinationColCount(false, ImportDestination, DataSet,
                  DBGrid, ListView, StringGrid) - 1 do
    with lvCSVFields.Items.Add do begin
      Caption := QImportDestinationColName(false, ImportDestination, DataSet,
        DBGrid, Self.ListView, StringGrid, GridCaptionRow, i);
      SubItems.Add(EmptyStr);
    end;
end;

procedure TQImport2WizardF.CSVClearCombo;
begin
  lvCSVFields.Items.Clear;
end;

procedure TQImport2WizardF.CSVTune;
begin
  ShowTip(tsCSVOptions, 6, 21, 39, 557, {$IFDEF WIN32}QImportLoadStr(QIW_CSV_Tip){$ENDIF}
                                        {$IFDEF LINUX}QIW_CSV_Tip{$ENDIF});

  pgImport.ActivePage := tsCSVOptions;
  laStep_07.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                              {$IFDEF LINUX}QIW_Step{$ENDIF}, [1, 3]);

  if FNeedLoadFile then CSVFillGrid;

  if (lvCSVFields.Items.Count > 0) and
     not Assigned(lvCSVFields.Selected) then begin
    lvCSVFields.Items[0].Focused := true;
    lvCSVFields.Items[0].Selected := true;
  end;
  TuneButtons;
end;

function TQImport2WizardF.CSVReady: boolean;
var
  i: integer;
begin
  Result := false;
  for i := 0 to lvCSVFields.Items.Count - 1 do begin
    Result := StrToIntDef(lvCSVFields.Items[i].SubItems[0], 0) > 0;
    if Result then Break;
  end;
end;

procedure TQImport2WizardF.CSVFillGrid;
var
  F: TextFile;
  n, i, m: integer;
  Str: string;
  Strings: TStrings;
  List: TList;
begin
  for i := 0 to sgrCSV.RowCount - 1 do
    for n := 0 to sgrCSV.ColCount - 1 do
      sgrCSV.Cells[n, i] := EmptyStr;

  if not FileExists(FileName) then Exit;
  AssignFile(F, FileName);
  Reset(F);
  try
    Strings := TStringList.Create;
    try
      List := TList.Create;
      try
        n := 0;
        m := Wizard.CSVViewerRows;
        while not EOF(F) and ((m <= 0) or (n <= m)) do begin
          Readln(F, Str);
          CSVStringToStrings(Str, Quote, Comma, Strings);
          for i := 0 to Strings.Count - 1 do begin
            if List.Count < i + 1 then List.Add(Pointer(Length({$IFDEF WIN32}QImportLoadStr(QIW_CSV_GridCol){$ENDIF}
                                                               {$IFDEF LINUX}QIW_CSV_GridCol{$ENDIF})));
            if Integer(List[i]) < Length(Strings[i]) then
              List[i] := Pointer(Length(Strings[i]));
            if sgrCSV.ColCount < List.Count then
              sgrCSV.ColCount := List.Count;
            sgrCSV.Cells[i, n + 1] := Strings[i];
          end;
          Inc(n);
        end;
        sgrCSV.ColCount := List.Count;
        cbCSVColNumber.Items.Clear;
        cbCSVColNumber.Items.Add(EmptyStr);
        for i := 0 to List.Count - 1 do begin
          sgrCSV.ColWidths[i] := sgrCSV.Canvas.TextWidth('X') * (Integer(List[i]) + 1);
          sgrCSV.Cells[i, 0] := Format({$IFDEF WIN32}QImportLoadStr(QIW_CSV_GridCol){$ENDIF}
                                       {$IFDEF LINUX}QIW_CSV_GridCol{$ENDIF}, [i + 1]);
          cbCSVColNumber.Items.Add(IntToStr(i + 1));
        end;
        sgrCSV.RowHeights[0] := 18;
      finally
        List.Free;
      end;
    finally
      Strings.Free;
    end;
  finally
    CloseFile(F);
  end;
  FNeedLoadFile := false;
end;

function TQImport2WizardF.CSVCol: integer;
begin
  Result := 0;
  if Assigned(lvCSVFields.Selected) then
    Result := StrToIntDef(lvCSVFields.Selected.SubItems[0], 0);
end;

procedure TQImport2WizardF.sgrCSVDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  X, Y: integer;
begin
  X := Rect.Left + (Rect.Right - Rect.Left -
   sgrCSV.Canvas.TextWidth(sgrCSV.Cells[ACol, ARow])) div 2;
  Y := Rect.Top + (Rect.Bottom - Rect.Top -
    sgrCSV.Canvas.TextHeight(sgrCSV.Cells[ACol, ARow])) div 2;
  if gdFixed in State then begin
    if (ACol = CSVCol - 1) and (ARow = 0)
      then sgrCSV.Canvas.Font.Style := sgrCSV.Canvas.Font.Style + [fsBold]
      else sgrCSV.Canvas.Font.Style := sgrCSV.Canvas.Font.Style - [fsBold];
    sgrCSV.Canvas.FillRect(Rect);
    sgrCSV.Canvas.TextOut(X - 1, Y + 1, sgrCSV.Cells[ACol, ARow]);
  end
  else begin
    sgrCSV.DefaultDrawing := false;
    sgrCSV.Canvas.Brush.Color := clWindow;
    sgrCSV.Canvas.FillRect(Rect);
    sgrCSV.Canvas.Font.Color := clWindowText;
    sgrCSV.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2,
      sgrCSV.Cells[ACol, ARow]);

    if (ACol = CSVCol - 1) and (ARow > 0) then begin
      sgrCSV.Canvas.Font.Color := clHighLightText;
      sgrCSV.Canvas.Brush.Color := clHighLight;
      Rect.Bottom := Rect.Bottom + 1;
      sgrCSV.Canvas.FillRect(Rect);
      sgrCSV.Canvas.TextOut(Rect.Left + 2, Y, sgrCSV.Cells[ACol, ARow]);
      Rect.Bottom := Rect.Bottom - 1;
    end;
  end;
  if gdFocused in State
    then DrawFocusRect(sgrCSV.Canvas.Handle, Rect);
  sgrCSV.DefaultDrawing := true;
end;

procedure TQImport2WizardF.edtCSVSkipLinesChange(Sender: TObject);
begin
  CSVSkipLines := StrToIntDef(edtCSVSkipLines.Text, 0);
end;

procedure TQImport2WizardF.btnCSVClearClick(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to lvCSVFields.Items.Count - 1 do
    lvCSVFields.Items[i].SubItems[0] := EmptyStr;
  lvCSVFieldsChange(lvCSVFields, lvCSVFields.Selected, ctState);
end;

procedure TQImport2WizardF.sgrCSVMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  ACol, ARow: integer;
begin
  sgrCSV.MouseToCell(X, Y, ACol, ARow);
  if not Assigned(lvCSVFields.Selected) then Exit;
  if CSVCol = ACol + 1
    then lvCSVFields.Selected.SubItems[0] := EmptyStr
    else lvCSVFields.Selected.SubItems[0] := IntToStr(ACol + 1);
  lvCSVFieldsChange(lvCSVFields, lvCSVFields.Selected, ctState);
end;

procedure TQImport2WizardF.lvCSVFieldsChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
begin
  if not Assigned(Item) then Exit;
  cbCSVColNumber.OnChange := nil;
  try
    if Item.SubItems.Count > 0 then
      cbCSVColNumber.ItemIndex := cbCSVColNumber.Items.IndexOf(Item.SubItems[0]);
    sgrCSV.Repaint;
    TuneButtons;
  finally
    cbCSVColNumber.OnChange := cbCSVColNumberChange;;
  end;
end;

procedure TQImport2WizardF.cbCSVColNumberChange(Sender: TObject);
begin
  if not Assigned(lvCSVFields.Selected) then Exit;
  lvCSVFields.Selected.SubItems[0] := cbCSVColNumber.Text;
  sgrCSV.Repaint;
end;

procedure TQImport2WizardF.btnCSVAutoFillClick(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to lvCSVFields.Items.Count - 1 do
    if (i <= sgrCSV.ColCount - 1)
      then lvCSVFields.Items[i].SubItems[0] := IntToStr(i + 1)
      else lvCSVFields.Items[i].SubItems[0] := EmptyStr;
  lvCSVFieldsChange(lvCSVFields, lvCSVFields.Selected, ctState);
end;

procedure TQImport2WizardF.SetCSVSkipLines(const Value: integer);
begin
  if FCSVSkipLines <> Value then begin
    FCSVSkipLines := Value;
    edtCSVSkipLines.Text := IntToStr(FCSVSkipLines);
  end;
end;

// DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF
// DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF
// DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF DBF

procedure TQImport2WizardF.DBFFillList;
var
  i: integer;
begin
  if not (aiDBF in Wizard.AllowedImports) then Exit;
  DBFClearList;
  for i := 0 to QImportDestinationColCount(false, ImportDestination, DataSet,
                  DBGrid, ListView, StringGrid) - 1 do
    lstDBFDataSet.Items.Add.Caption :=
      QImportDestinationColName(false, ImportDestination, DataSet, DBGrid,
        ListView, StringGrid, GridCaptionRow, i);
  if lstDBFDataSet.Items.Count > 0 then  begin
    lstDBFDataSet.Items[0].Focused := true;
    lstDBFDataSet.Items[0].Selected := true;
  end;
end;

procedure TQImport2WizardF.DBFClearList;
var
  i: integer;
begin
  for i := lstDBFDataSet.Items.Count - 1 downto 0 do
    lstDBFDataSet.Items.Delete(i);
end;

procedure TQImport2WizardF.DBFFillTableList;
var
  DBF: TDBFRead;
  i: integer;
begin
  DBFClearTableList;
  DBF := TDBFRead.Create(FileName);
  try
    for i := 0 to DBF.FieldCount - 1 do
      lstDBF.Items.Add.Caption := DBF.FieldName[i];
    if lstDBF.Items.Count > 0 then begin
      lstDBF.Items[0].Focused := true;;
      lstDBF.Items[0].Selected := true;;
    end;
    lstDBF.Columns[0].Caption := ExtractFileName(FileName);
  finally
    DBF.Free;
  end;
  FNeedLoadFile := false;
end;

procedure TQImport2WizardF.DBFClearTableList;
var
 i: integer;
begin
  for i := lstDBF.Items.Count - 1 downto 0 do
    lstDBF.Items.Delete(i);
end;

procedure TQImport2WizardF.DBFTune;
begin
  ShowTip(tsDBFOptions, 6, 21, 39, 557, {$IFDEF WIN32}QImportLoadStr(QIW_DBF_Tip){$ENDIF}
                                        {$IFDEF LINUX}QIW_DBF_Tip{$ENDIF});

  if FNeedLoadFile then DBFFillTableList;
  pgImport.ActivePage := tsDBFOptions;
  laStep_03.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                              {$IFDEF LINUX}QIW_Step{$ENDIF}, [1,3]);
  TuneButtons;
end;

procedure TQImport2WizardF.lstDBFDataSetChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
begin
  TuneButtons;
end;

procedure TQImport2WizardF.lstDBFChange(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  TuneButtons;
end;

procedure TQImport2WizardF.lstDBFMapChange(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  TuneButtons;
end;

procedure TQImport2WizardF.SetDBFSkipDeleted(const Value: Boolean);
begin
  if FDBFSkipDeleted <> Value then begin
    FDBFSkipDeleted := Value;
    chDBFSkipDeleted.Checked := FDBFSkipDeleted;
  end;
end;

procedure TQImport2WizardF.chDBFSkipDeletedClick(Sender: TObject);
begin
  DBFSkipDeleted := chDBFSkipDeleted.Checked;
end;

procedure TQImport2WizardF.pbDBFAddPaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bDBFAdd.Enabled
      then i := 4
      else i := 12;
    ilWizard.GetBitmap(i, Bmp);
    pbDBFAdd.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bDBFAddMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFAdd.Left := pbDBFAdd.Left + 1;
  pbDBFAdd.Top := pbDBFAdd.Top + 1;
end;

procedure TQImport2WizardF.bDBFAddMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFAdd.Left := pbDBFAdd.Left - 1;
  pbDBFAdd.Top := pbDBFAdd.Top - 1;
end;

procedure TQImport2WizardF.pbDBFAutoFillPaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bDBFAutoFill.Enabled
      then i := 9
      else i := 17;
    ilWizard.GetBitmap(i, Bmp);
    pbDBFAutoFill.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bDBFAutoFillMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFAutoFill.Left := pbDBFAutoFill.Left + 1;
  pbDBFAutoFill.Top := pbDBFAutoFill.Top + 1;
end;

procedure TQImport2WizardF.bDBFAutoFillMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFAutoFill.Left := pbDBFAutoFill.Left - 1;
  pbDBFAutoFill.Top := pbDBFAutoFill.Top - 1;
end;

procedure TQImport2WizardF.pbDBFRemovePaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bDBFRemove.Enabled
      then i := 6
      else i := 14;
    ilWizard.GetBitmap(i, Bmp);
    pbDBFRemove.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bDBFRemoveMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFRemove.Left := pbDBFRemove.Left + 1;
  pbDBFRemove.Top := pbDBFRemove.Top + 1;
end;

procedure TQImport2WizardF.bDBFRemoveMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFRemove.Left := pbDBFRemove.Left - 1;
  pbDBFRemove.Top := pbDBFRemove.Top - 1;
end;

procedure TQImport2WizardF.pbDBFClearPaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bDBFClear.Enabled
      then i := 7
      else i := 15;
    ilWizard.GetBitmap(i, Bmp);
    pbDBFClear.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bDBFClearMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFClear.Left := pbDBFClear.Left + 1;
  pbDBFClear.Top := pbDBFClear.Top + 1;
end;

procedure TQImport2WizardF.bDBFClearMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbDBFClear.Left := pbDBFClear.Left - 1;
  pbDBFClear.Top := pbDBFClear.Top - 1;
end;

// XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML
// XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML
// XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML XML
procedure TQImport2WizardF.SetXMLWriteOnFly(const Value: boolean);
begin
  if FXMLWriteOnFly <> Value then begin
    FXMLWriteOnFly := Value;
    chXMLWriteOnFly.Checked := FXMLWriteOnFly;
  end;
end;

procedure TQImport2WizardF.chXMLWriteOnFlyClick(Sender: TObject);
begin
  XMLWriteOnFly := chXMLWriteOnFly.Checked;
end;

procedure TQImport2WizardF.bXMLAddClick(Sender: TObject);
begin
  with lvXMLMap.Items.Add do begin
    Caption := lvXMLDataSet.Selected.Caption;
    SubItems.Add('=');
    SubItems.Add(lvXML.Selected.Caption);
    Focused := true;
    Selected := true;
  end;
  lvXMLDataSet.Items.Delete(lvXMLDataSet.Selected.Index);
  if lvXMLDataSet.Items.Count > 0 then begin
    lvXMLDataSet.Items[0].Focused := true;
    lvXMLDataSet.Items[0].Selected := true;
  end;
  if lvXMLMap.Items.Count > 0 then begin
    lvXMLMap.Items[0].Focused := true;
    lvXMLMap.Items[0].Selected := true;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.bXMLAutoFillClick(Sender: TObject);
var
  i, N: integer;
begin
  lvXMLDataSet.Items.BeginUpdate;
  try
    lvXML.Items.BeginUpdate;
    try
      lvXMLMap.Items.BeginUpdate;
      try
        lvXMLMap.Items.Clear;
        XMLClearList;
        XMLFillList;
        N := lvXML.Items.Count;
        if N > lvXMLDataSet.Items.Count
          then N := lvXMLDataSet.Items.Count;
        for i := N - 1 downto 0 do begin
          with lvXMLMap.Items.Insert(0) do begin
            Caption := lvXMLDataSet.Items[i].Caption;
            SubItems.Add('=');
            SubItems.Add(lvXML.Items[i].Caption);
          end;
          lvXMLDataSet.Items[i].Delete;
        end;
        if lvXMLMap.Items.Count > 0 then begin
          lvXMLMap.Items[0].Focused := true;
          lvXMLMap.Items[0].Selected := true;
        end;
      finally
        lvXMLMap.Items.EndUpdate;
      end;
    finally
      lvXML.Items.EndUpdate;
    end;
  finally
    lvXMLDataSet.Items.EndUpdate;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.bXMLRemoveClick(Sender: TObject);
begin
  lvXMLDataSet.Items.Add.Caption := lvXMLMap.Selected.Caption;
  lvXMLMap.Items.Delete(lvXMLMap.Selected.Index);
  if lvXMLMap.Items.Count > 0 then begin
    lvXMLMap.Items[0].Focused := true;
    lvXMLMap.Items[0].Selected := true;
  end;
  if lvXMLDataSet.Items.Count > 0 then begin
    lvXMLDataSet.Items[0].Focused := true;
    lvXMLDataSet.Items[0].Selected := true;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.bXMLClearClick(Sender: TObject);
begin
  lvXMLDataSet.Items.BeginUpdate;
  try
    lvXMLMap.Items.BeginUpdate;
    try
      lvXMLMap.Items.Clear;
      XMLClearList;
      XMLFillList;
    finally
      lvXMLMap.Items.EndUpdate;
    end;
  finally
    lvXMLDataSet.Items.EndUpdate;
  end;
  TuneButtons;
end;

function TQImport2WizardF.XMLReady: boolean;
begin
  Result := lvXMLMap.Items.Count > 0;
end;

procedure TQImport2WizardF.XMLFillList;
var
  i: integer;
begin
  if not (aiXML in Wizard.AllowedImports) then Exit;
  XMLClearList;
  for i := 0 to QImportDestinationColCount(false, ImportDestination, DataSet,
                  DBGrid, ListView, StringGrid) - 1 do
    lvXMLDataSet.Items.Add.Caption :=
      QImportDestinationColName(false, ImportDestination, DataSet, DBGrid,
        ListView, StringGrid, GridCaptionRow, i);
  if lvXMLDataSet.Items.Count > 0 then  begin
    lvXMLDataSet.Items[0].Focused := true;
    lvXMLDataSet.Items[0].Selected := true;
  end;
end;

procedure TQImport2WizardF.XMLClearList;
var
  i: integer;
begin
  for i := lvXMLDataSet.Items.Count - 1 downto 0 do
    lvXMLDataSet.Items.Delete(i);
end;

procedure TQImport2WizardF.XMLFillTableList;
var
  XML: TXMLFile;
  i: integer;
  str: string;
begin
  XMLClearTableList;
  XML := TXMLFile.Create;
  try
    XML.FileName := FileName;
    XML.Clear;
    XML.Load(true);
    if not Assigned(XML.Fields) then
      raise EQImportError.Create({$IFDEF WIN32}QImportLoadStr(QIE_XMLFieldListEmpty){$ENDIF}
                                 {$IFDEF LINUX}QIE_XMLFieldListEmpty{$ENDIF});

    for i := 0 to XML.FieldCount - 1 do begin
      str := EmptyStr;
      if XML.Fields[i].Attributes.IndexOfName('attrname') > -1 then
        str := 'attrname'
      else if XML.Fields[i].Attributes.IndexOfName('FieldName') > -1 then
        str := 'FieldName';
      if str = EmptyStr then raise EQImportError.Create('XML read with errors');

      lvXML.Items.Add.Caption := XML.Fields[i].Attributes.Values[str];
    end;
    if lvXML.Items.Count > 0 then begin
      lvXML.Items[0].Focused := true;;
      lvXML.Items[0].Selected := true;;
    end;
    lvXML.Columns[0].Caption := ExtractFileName(FileName);
  finally
    XML.Free;
  end;
  FNeedLoadFile := false;
end;

procedure TQImport2WizardF.XMLClearTableList;
var
 i: integer;
begin
  for i := lvXML.Items.Count - 1 downto 0 do
    lvXML.Items.Delete(i);
end;

procedure TQImport2WizardF.XMLTune;
begin
  ShowTip(tsXMLOptions, 6, 21, 39, 557, {$IFDEF WIN32}QImportLoadStr(QIW_XML_Tip){$ENDIF}
                                        {$IFDEF LINUX}QIW_XML_Tip{$ENDIF});

  if FNeedLoadFile then XMLFillTableList;
  pgImport.ActivePage := tsXMLOptions;
  laStep_05.Caption := Format({$IFDEF WIN32}QImportLoadStr(QIW_Step){$ENDIF}
                              {$IFDEF LINUX}QIW_Step{$ENDIF}, [1,3]);
  TuneButtons;
end;

procedure TQImport2WizardF.pbXMLAddPaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bXMLAdd.Enabled
      then i := 4
      else i := 12;
    ilWizard.GetBitmap(i, Bmp);
    pbXMLAdd.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bXMLAddMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLAdd.Left := pbXMLAdd.Left + 1;
  pbXMLAdd.Top := pbXMLAdd.Top + 1;
end;

procedure TQImport2WizardF.bXMLAddMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLAdd.Left := pbXMLAdd.Left - 1;
  pbXMLAdd.Top := pbXMLAdd.Top - 1;
end;

procedure TQImport2WizardF.pbXMLAutoFillPaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bXMLAutoFill.Enabled
      then i := 9
      else i := 17;
    ilWizard.GetBitmap(i, Bmp);
    pbXMLAutoFill.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bXMLAutoFillMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLAutoFill.Left := pbXMLAutoFill.Left + 1;
  pbXMLAutoFill.Top := pbXMLAutoFill.Top + 1;
end;

procedure TQImport2WizardF.bXMLAutoFillMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLAutoFill.Left := pbXMLAutoFill.Left - 1;
  pbXMLAutoFill.Top := pbXMLAutoFill.Top - 1;
end;

procedure TQImport2WizardF.pbXMLRemovePaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bXMLRemove.Enabled
      then i := 6
      else i := 14;
    ilWizard.GetBitmap(i, Bmp);
    pbXMLRemove.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bXMLRemoveMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLRemove.Left := pbXMLRemove.Left + 1;
  pbXMLRemove.Top := pbXMLRemove.Top + 1;
end;

procedure TQImport2WizardF.bXMLRemoveMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLRemove.Left := pbXMLRemove.Left - 1;
  pbXMLRemove.Top := pbXMLRemove.Top - 1;
end;

procedure TQImport2WizardF.pbXMLClearPaint(Sender: TObject);
var
  Bmp: TBitmap;
  i: integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Transparent := true;
    if bXMLClear.Enabled
      then i := 7
      else i := 15;
    ilWizard.GetBitmap(i, Bmp);
    pbXMLClear.Canvas.Draw(0, 0, Bmp)
  finally
    Bmp.Free;
  end;
end;

procedure TQImport2WizardF.bXMLClearMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLClear.Left := pbXMLClear.Left + 1;
  pbXMLClear.Top := pbXMLClear.Top + 1;
end;

procedure TQImport2WizardF.bXMLClearMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pbXMLClear.Left := pbXMLClear.Left - 1;
  pbXMLClear.Top := pbXMLClear.Top - 1;
end;

procedure TQImport2WizardF.tbtAddReplacementClick(Sender: TObject);
var
  TextToFind, ReplaceWith: string;
  IgnoreCase: boolean;
  R: TQImportReplacement;
begin
  TextToFind := EmptyStr;
  ReplaceWith := EmptyStr;
  IgnoreCase := false;
  if ReplacementEdit(TextToFind, ReplaceWith, IgnoreCase) then begin
    R := TQImportFieldFormat(lstFormatFields.ItemFocused.Data).Replacements.Add;
    R.TextToFind := TextToFind;
    R.ReplaceWith := ReplaceWith;
    R.IgnoreCase := IgnoreCase;
    with lvReplacements.Items.Add do begin
      Caption := R.TextToFind;
      SubItems.Add(R.ReplaceWith);
      if R.IgnoreCase
        then SubItems.Add({$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase_Yes){$ENDIF}
                          {$IFDEF LINUX}QIWDF_IgnoreCase_Yes{$ENDIF})
        else SubItems.Add({$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase_No){$ENDIF}
                          {$IFDEF LINUX}QIWDF_IgnoreCase_No{$ENDIF});
      ImageIndex := 3;
      Data := R;
      Focused := true;
      Selected := true;
    end;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.lvReplacementsChange(Sender: TObject;
  Item: TListItem; Change: TItemChange);
begin
  TuneButtons;
end;

procedure TQImport2WizardF.tbtEditReplacementClick(Sender: TObject);
var
  TextToFind, ReplaceWith: string;
  IgnoreCase: boolean;
  R: TQImportReplacement;
begin
  R := TQImportReplacement(lvReplacements.ItemFocused.Data);
  TextToFind := R.TextToFind;
  ReplaceWith := R.ReplaceWith;
  IgnoreCase := R.IgnoreCase;
  if ReplacementEdit(TextToFind, ReplaceWith, IgnoreCase) then begin
    R.TextToFind := TextToFind;
    R.ReplaceWith := ReplaceWith;
    R.IgnoreCase := IgnoreCase;
    with lvReplacements.ItemFocused do begin
      Caption := R.TextToFind;
      SubItems[0] := R.ReplaceWith;
      if R.IgnoreCase
        then SubItems[1] := {$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase_Yes){$ENDIF}
                            {$IFDEF LINUX}QIWDF_IgnoreCase_Yes{$ENDIF}
        else SubItems[1] := {$IFDEF WIN32}QImportLoadStr(QIWDF_IgnoreCase_No){$ENDIF}
                            {$IFDEF LINUX}QIWDF_IgnoreCase_No{$ENDIF};
    end;
  end;
  TuneButtons;
end;

procedure TQImport2WizardF.tbtDelReplacementClick(Sender: TObject);
begin
  TQImportReplacement(lvReplacements.ItemFocused.Data).Free;
  lvReplacements.ItemFocused.Delete;
  TuneButtons;
end;

procedure TQImport2WizardF.lvReplacementsDblClick(Sender: TObject);
begin
  if tbtEditReplacement.Enabled then
    tbtEditReplacement.Click; 
end;

procedure TQImport2WizardF.lvXLSFieldsEnter(Sender: TObject);
begin
  XLSRepaintCurrentGrid;
end;

procedure TQImport2WizardF.lvXLSFieldsExit(Sender: TObject);
begin
  XLSRepaintCurrentGrid;
end;

procedure TQImport2WizardF.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  if Wizard.ConfirmOnCancel then
  begin
    CanClose := (Application.MessageBox(PChar({$IFDEF WIN32}QImportLoadStr(QIW_CancelWizard){$ENDIF}
                                     {$IFDEF LINUX}QIW_CancelWizard{$ENDIF}),
                               PChar({$IFDEF WIN32}QImportLoadStr(QIW_Question){$ENDIF}
                                     {$IFDEF LINUX}QIW_Question{$ENDIF}),
          MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2) = ID_YES);
  end;
  if CanClose and AutoSaveTemplate then
    SaveTemplateToFile(TemplateFileName);
end;

function TQImport2WizardF.AllowedImportFileType(
  const AFileName: string): Boolean;
var
  ext: string;
begin
  ext := LowerCase(ExtractFileExt(AFileName));
  Result := (ext = XLS_EXT) or
            (ext = DBF_EXT) or
            (ext = DB_EXT) or
            (ext = XML_EXT) or
            (ext = TXT_EXT) or
            (ext = CSV_EXT);
end;

function TQImport2WizardF.ImportTypeEquivFileType(const AFileName: string): Boolean;
var
  ext: string;
begin
  ext := LowerCase(ExtractFileExt(AFileName));
  Result := ImportTypeStr(ImportType) = ext;
end;

function TQImport2WizardF.ImportTypeStr(
  AImportType: TAllowedImport): string;
begin
  Result := '';
  case AImportType of
    aiXLS: Result := XLS_EXT;
    aiDBF: Result := DBF_EXT;
    aiXML: Result := XML_EXT;
    aiTXT: Result := TXT_EXT;
    aiCSV: Result := CSV_EXT;
  end;
end;

end.
